关于mobx:store变化了而页面取不到值mobx会对什么作出反应

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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理