React / Mobx 全局状态管理问题

2022-05-09 11:30:26 +08:00
 taofoo

学习 React 看到了这个帖子 https://zhuanlan.zhihu.com/p/114292057

大概说的内容是用 mobx 创建了一个 TodoStore 实现了全局的状态管理。 问题在这里,既然用了 mobx 为何还要用 Provider?不是很明白。通过 observer 不是已经可以监听 store 的变化了吗?

下面是代码贴的是上面帖子里面的

// ./src/app.tsx
import React from 'react';
import { Provider } from 'mobx-react';
import Routers from './containers/routers';
import { stores, StoresContext } from './stores';

function App() {
  return (
    // 服务类组件
    <Provider {...stores}>
      {/* 服务函数组件 */}
      <StoresContext.Provider value={stores}>
        <Routers />
      </StoresContext.Provider>
    </Provider>
  );
}

export default App;
// ./src/containers/todo-list-fn/index.tsx
import React from 'react';
import { observer } from 'mobx-react';
import { useTodoStore } from '../../stores';

function TodoListFnPage() {
  const {
    todos,
    undoneCount,
    doneCount,
    addNewTodo,
    removeById,
    toggleStatusById
  } = useTodoStore();

// 注意这里的 observer
export default observer(TodoListFnPage);
2703 次点击
所在节点    React
22 条回复
CodingNaux
2022-05-09 11:37:50 +08:00
你看的资料有些过时,直接看官方文档吧,现在都是用 mobx-react-lite ,装饰器写法已经不推荐了
https://mobx.js.org/react-integration.html
statumer
2022-05-09 11:41:53 +08:00
官方有文档为什么要看三流学习笔记
CodingNaux
2022-05-09 11:43:35 +08:00
至于你说为什么还要多此一举用 Provider ,旧的文档这么写就这么用吧,深究需要看代码,一个 mobx 与 react 的 adapter 代码也不会太多
cszchen
2022-05-09 11:48:43 +08:00
不明觉厉,我之前做一个简单的项目,用的 resso
taofoo
2022-05-09 11:53:45 +08:00
@CodingNaux 好的,我自己没用 Context 那一套,直接用 mobx 是可以的。有待深究🤣
taofoo
2022-05-09 11:54:17 +08:00
@CodingNaux 嗯,瞅瞅去
taofoo
2022-05-09 11:59:39 +08:00
@statumer 🤣确实,不过我简略的过一遍 react 遇到全局状态问题,想找一个完整一点的例子。搜了一下看到了这个
taofoo
2022-05-09 12:00:47 +08:00
@cszchen 之前看到过,挺小的
statumer
2022-05-09 12:13:59 +08:00
@taofoo mobx 是可以和 context 一起用的,很简单就可以实现按需更新,而不是重渲染所有 Context Consumer 组件( React Context 的默认行为)。官网就有示例。
otakustay
2022-05-09 12:24:18 +08:00
放在以前,没有 Provider 大致也是行的,包括 redux 如果你是严格单 store ,其实也能直接拿 store 过来再 getState 玩,自己去 listen 就行
总体上用 Provider 应该有 2 个考虑:
1. 所有版本下,如果你要支持多个 store ,那就得用不同位置的 Provider 区分下面的子组件用哪个 store
2. 在 React 18 以后的并发模式下,直接用 store 会状态撕裂,所以要用 useExternalSyncStore ,这东西还是挺复杂的,损耗也不少,所以最好在 Provider 上集中处理再丢给下面
taofoo
2022-05-09 12:29:47 +08:00
@statumer 那使用 observer 在 store 更新的时候会重新渲染所有引用 store 的组件的吗?
taofoo
2022-05-09 12:38:12 +08:00
@otakustay 对于第二点没啥问题。对于第一点,Provider 是不是更像是一种规范?因为子组件也可以自己直接导入 store 。不知道这么理解对不对
gogogo1203
2022-05-09 13:11:06 +08:00
如果想更方便可以改用 zustand
otakustay
2022-05-09 13:33:44 +08:00
@taofoo #12 子组件自己导入就形成了耦合了,用 Provider 的话可以在 Provider 层面换一个结构一样的 store 。有一些比较极端的实现,比如一个列表 List 里,每个 ListItem 都套一个 Provider 提供当前的 item 数据,这种时候显然子组件考虑自己的通用性,不可能去直接导入 store
taofoo
2022-05-09 13:36:47 +08:00
@otakustay 嗯,有点想通了,我在想想。多谢解答!
taofoo
2022-05-09 13:44:53 +08:00
@gogogo1203 react 选择这么多样化的吗 ,哈哈
L1shen
2022-05-09 14:39:37 +08:00
还可以用 valtio
gogogo1203
2022-05-09 15:31:47 +08:00
gogogo1203
2022-05-09 15:36:26 +08:00
@taofoo 不管用什么 global state manager , 用 reducer pattern+ immer 应该都差不多. 怎么方便怎么来吧。 用 React-Query 来管来自服务器的数据,用 zustand 管 client side state.
ljpCN
2022-05-09 16:01:08 +08:00
个人理解。Provider 在于可以隔离。外部代码使用你编写的组件时,可以在多个地方使用,而他们的内部状态不能引用同一个 mobx 实例,使用 provider 可以保证每个组件内的 mobx 实例是来自它自己的顶层 provider 。两颗组件树访问不同的实例。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/851701

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX