V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
taofoo
V2EX  ›  React

React / Mobx 全局状态管理问题

  •  
  •   taofoo · 2022-05-09 11:30:26 +08:00 · 3033 次点击
    这是一个创建于 963 天前的主题,其中的信息可能已经有所发展或是发生改变。

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