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>}