共计 2747 个字符,预计需要花费 7 分钟才能阅读完成。
1、没有封装成observer
组件
容器组件
import Change from './Change';
import Father from './Father';
const Main = (props: any) => {
return (
<div>
<Father></Father>
<Change></Change>
</div>
)
}
export default Main;
Father 组件
import {inject} from 'mobx-react';
import React from 'react';
import Store from '../../store/store';
interface IProps {store?: Store;}
const Father = (props: IProps) => {const { store} = props;
const {message} = store as Store;
return <div>
<div>title: {message.title}</div>
<div>author: {message.author.name}</div>
<div>likes: {message.likes[0]}</div>
</div>
}
export default inject('store')(Father);
Change 组件
import {Divider} from 'antd';
import {inject, observer} from 'mobx-react';
import React from 'react';
import Store from '../../store/store';
interface IProps {store?: Store;}
const Change = (props: IProps) => {const { store} = props;
const {setName, setTitle, setLikes} = store as Store;
return <div>
<button onClick={() => setTitle('spin')}> 扭转 title</button>
<button onClick={() => setName('tom')}> 扭转 name</button>
<button onClick={() => setLikes('john')}> 扭转 likes</button>
</div>
}
export default inject('store')(observer(Change));
store
import {observable, action} from 'mobx';
class Store {
@observable message = {
title: 'Bar',
author: {name: 'Susan'},
likes: ['Michel']
}
@action
setTitle = (title: string) => {this.message.title = title;}
@action
setName = (name: string) => {this.message.author.name = name;}
@action
setLikes = (target: string) => {this.message.likes[0] = target;
}
}
export default Store;
当点击扭转 title、name、likes 按钮时,store 中察看对象 message 的属性值扭转了,然而 Father 组件并没有从新渲染。因为 Father 组件并不是 observer 组件,只有封装成 observer 组件,mobx 才会对 render 函数(函数组件了解为 return 返回的 ReactNode)中 读取 现存的可察看属性做出反馈。
因而,只须要将 Father 组件封装成 observer 组件就能够解决
export default inject('store')(Father);
改后
export default inject('store')(observer(Father));
2、MobX 只会为数据是间接通过 render
存取的 observer
组件进行数据追踪
Father 组件
const Father = (props: IProps) => {const { store} = props;
const {message} = store as Store;
return <div>
<div>title: {message.title}</div>
<Child title={() => <div>{message.author.name}</div>}></Child>
<div>likes: {message.likes[0]}</div>
</div>
}
export default inject('store')(observer(Father));
Child 组件
interface IProps {title: () => React.ReactNode;
}
const Child = (props: IProps) => {const { title} = props;
return <div>{title()}</div>
}
export default Child;
当扭转 store 中 message.author.name 时,页面并不会从新渲染。因为 div 实际上不是由 Father
(有追踪的渲染) 渲染的,而是 Child
。所以要确保 Child
的 title 能够正确对新的 message.author.name
作出反应,Child
应该也是一个 observer
。
如果 Child
来源于内部库的话,这通常不在你的掌控之中。在这种场景下,你能够用本人的无状态 observer
组件来包裹 div
解决此问题,或通过利用 <Observer>
组件:
// 将 Child 改成 observer 组件
const Child = (props: IProps) => {const { title} = props;
return <div>{title()}</div>
}
export default observer(Child);
另外一种办法能够应用 mobx-react 内置的 Observer
组件,它不承受参数,只须要 单个的 render 函数作为子节点:
const Father = (props: IProps) => {const { store} = props;
const {message} = store as Store;
return <div>
<div>title: {message.title}</div>
<Child title={() => <Observer>{() => <div>{message.author.name}</div>}</Observer>}></Child>
<div>likes: {message.likes[0]}</div>
</div>
}
正文完