这篇文章讲一讲平时使用mobx时常遇到的一种store变化了而页面取不到值的场景——new了两个store实例

假设现在有一个storeA,里面存放了一个属性a,在组件A挂载完成时调接口获取数据并赋给属性a。现在有另外一个组件B也需要用到属性a,组件B先再次生成一份storeA并通过Provide注入,然后在里头获取属性a,发现获取不到。

这是因为组件A依赖的storeA实例与组件B依赖的storeA实例并不是同一个引用,每次new都会生成一个新的store实例,store的使用遵循就近原则。

image.png

下面举个例子说明:

全局store

import UserInfoStore from "./UserInfoStore";

export default {
  userInfoStore: new UserInfoStore()
}

注入全局store

ReactDOM.render(
  <HashRouter>
    <Provider {...stores}>
      {renderRoutes(routes)}
    </Provider>
  </HashRouter>,
  document.getElementById('root')
)

Layout组件中获取用户信息存放到全局的UserInfoStore

interface IProps extends RouteConfigComponentProps<void> {
  userInfoStore?: UserInfoStore
}

const Layout = (props: IProps) => {
  const {route, userInfoStore} = props

  const { fetchUserInfo } = userInfoStore as UserInfoStore;

  useEffect(() => {
    /** 获取用户信息 */
    fetchUserInfo();
  })

  return (
    <div className={styles.layout}>
      <div className={styles.header}>topbar</div>
      <div className={styles.menu}>slider</div>
      <div className={styles.content}>
        {renderRoutes(route?.routes)}
      </div>
      <div className={styles.footer}>footer</div>
    </div>
  )
}

export default inject('userInfoStore')(observer(Layout));

现在页面组件Page再次生成新的UserInfoStore并通过Provider注入

// 页面组件Page依赖的store
import PageStore from "./PageStore";
import UserInfoStore from "../../../store/UserInfoStore";

export default {
  pageStore: new PageStore(),
  userInfoStore: new UserInfoStore(), // 生成新的store实例
}

页面组件Page注入store

const Page = (props: Iprops) => {
  return <Provider {...stores}>
    <Main {...props}></Main>
  </Provider>
}

export default Page;
interface IProps extends RouteConfigComponentProps<void> {
  mainStore?: MainStore;
  userInfoStore?: UserInfoStore;
}

const Main = (props: IProps) => {

  const { mainStore, userInfoStore } = props;

  // 这里取到的是Page组件注入的userInfoStore实例,而不是全局store中的userInfoStore实例,因此获取不到用户信息
  const { userInfo } = userInfoStore as UserInfoStore;

  useEffect(() => {
    console.log('userInfo', userInfo)
  })

  return (
    <div>Main</div>
  )
}

export default inject('mainStore', 'userInfoStore')(observer(Main));

解决方法时Page组件不同另外再次生成userInfoStore,直接使用全局的userInfoStore


记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。