【发布时间】:2020-05-22 04:00:32
【问题描述】:
我是 MST 新手,很难找到更多异步操作示例。我有一个 api,它将根据您传递给它的参数返回不同的数据。在这种情况下,api 可以返回一组照片或教程。我已经为商店设置了我的初始值,如下所示:
data: {
photos: [],
tutorials: []
}
目前,我正在使用 applySnapshot 更新商店,最终,这将触发我的 React 组件的重新渲染。为了显示照片和教程,我需要调用 api 两次(一次是照片的参数,第二次是教程的参数)。我遇到了一个问题,即第一次更新的快照显示照片和教程具有相同的值,只有在第二次更新时,我才能获得正确的值。我可能误用 applySnapshot 来重新渲染我的 React 组件。我想知道这样做的更好/正确的方法。在 api 产生响应后重新渲染我的 React 组件的最佳方法是什么。任何建议都非常感谢
我的商店是这样设置的:
import { RootModel } from '.';
import { onSnapshot, getSnapshot, applySnapshot } from 'mobx-state-tree';
export const setupRootStore = () => {
const rootTree = RootModel.create({
data: {
photos: [],
tutorials: []
}
});
// on snapshot listener
onSnapshot(rootTree, snapshot => console.log('snapshot: ', snapshot));
return { rootTree };
};
我使用生成器创建了以下带有异步操作的模型:
import {types,Instance,applySnapshot,flow,onSnapshot} from 'mobx-state-tree';
const TestModel = types
.model('Test', {
photos: types.array(Results),
tutorials: types.array(Results)
})
.actions(self => ({
fetchData: flow(function* fetchData(param) {
const results = yield api.fetch(param);
applySnapshot(self, {
...self,
photos: [... results, ...self.photos],
tutorials: [... results, ...self.tutorials]
});
})
}))
.views(self => ({
getPhoto() {
return self.photos;
},
getTutorials() {
return self.tutorials;
}
}));
const RootModel = types.model('Root', {
data: TestModel
});
export { RootModel };
export type Root = Instance<typeof RootModel>;
export type Test = Instance<typeof TestModel>;
Photos.tsx 的反应组件
import React, { Component } from 'react';
import Spinner from 'components/Spinner';
import { Root } from '../../stores';
import { observer, inject } from 'mobx-react';
interface Props {
rootTree?: Root
}
@inject('rootTree')
@observer
class Photos extends Component<Props> {
componentDidMount() {
const { rootTree } = this.props;
if (!rootTree) return null;
rootTree.data.fetchData('photo');
}
componentDidUpdate(prevProps) {
if (prevProps.ctx !== this.props.ctx) {
const { rootTree } = this.props;
if (!rootTree) return null;
rootTree.data.fetchData('photo');
}
}
displayPhoto() {
const { rootTree } = this.props;
if (!rootTree) return null;
// calling method in MST view
const photoResults = rootTree.data.getPhoto();
if (photoResults.$treenode.snapshot[0]) {
return (
<div>
<div className='photo-title'>{'Photo'}</div>
{photoResults.$treenode.snapshot.map(Item => (
<a href={photoItem.attributes.openUrl} target='_blank'>
<img src={photoItem.url} />
</a>
))}
</div>
);
} else {
return <Spinner />;
}
}
render() {
return <div className='photo-module'>{this.displayPhoto()}</div>;
}
}
export default Photos;
同样,Tutorials.tsx 也是这样:
import React, { Component } from 'react';
import Spinner from '';
import { Root } from '../../stores';
import { observer, inject } from 'mobx-react';
interface Props {
rootTree?: Root;
}
@inject('rootTree')
@observer
class Tutorials extends Component<Props> {
componentDidMount() {
if (this.props.ctx) {
const { rootTree } = this.props;
if (!rootTree) return null;
rootTree.data.fetchData('tuts');
}
}
componentDidUpdate(prevProps) {
if (prevProps.ctx !== this.props.ctx) {
const { rootTree } = this.props;
if (!rootTree) return null;
rootTree.search.fetchData('tuts');
}
}
displayTutorials() {
const { rootTree } = this.props;
if (!rootTree) return null;
// calling method in MST view
const tutResults = rootTree.data.getTutorials();
if (tutResults.$treenode.snapshot[0]) {
return (
<div>
<div className='tutorials-title'>{'Tutorials'}</div>
{tutResults.$treenode.snapshot.map(tutorialItem => (
<a href={tutorialItem.attributes.openUrl} target='_blank'>
<img src={tutorialItem.url} />
</a>
))}
</div>
);
} else {
return <Spinner />;
}
}
render() {
return <div className='tutorials-module'>{this.displayTutorials()}</div>;
}
}
export default Tutorials;
【问题讨论】:
-
虽然此评论与 MobX 无关,但我强烈建议您为教程和照片使用单独的端点。它们是两种不同的实体类型,这只会导致混乱(并且难以维护代码)。对不起,我帮不上忙。希望有大神能来点更多的 MobX 体验,祝你好运!
标签: javascript reactjs mobx mobx-state-tree