[React] React 中, 为什么要用 Context? 直接使用全局变量不是更方便吗?

未免有点标题党, 且先看我写的这个 demo:

import React from 'react';
let obj = null;
let listener = null;
function getObj() { return obj; }
function setListener(l) { listener = l; }
function setObj(o) { obj = o; if (listener) { listener(o); }
}
function useObj() { const [, forceUpdate] = React.useReducer(x=>x+1,0); React.useEffect(() => { setListener(() => forceUpdate()) }, []) return getObj();
}
function Component1() { return ( <div> <button onClick={() => {setObj(Math.random())}}>setrandom</button> </div> )
}
function Component2() { const o = useObj(); return ( <div> {o} </div> )
}
export default function App() { return ( <div> <Component1 /> <Component2 /> </div> );
}

先说下 Context 一个缺点, 当数据改变时, 在 Context.Provider 下的节点都会重新执行, 这样很多不用其数据的节点也会被打扰, 昨天的帖子讨论过: 用 Context+Hooks 替代 Redux. 认真看了下大家的评论, 要么是用 memo 来固定住不想被打扰的组件, 要么使用一个订阅模式来刷新并通知.

与其这么麻烦, 不如直接用上面代码中的方法. 毕竟 Context 可以看作是一个全局的数据, 任意节点想使用这个数据时候, 还是需要 import 这个 Context.

上面代码和 redux 很像, 有一个 listener, 但 redux 需要靠 connect 绑定组件来订阅刷新, connect 利用了 Context.Provider+订阅+useSyncExternalStore 这个 API 来实现的.

还不如直接简简单单使用上面这种方式, 当节点使用全局数据时候, 使用自定义 hook 插一个 listener 进去, 当数据变动, 进行 forceUpdate. 这样也会避免了牵一发动全身的全部刷新, 只有使用 useObj() 的组件才会被刷新.

ps. 我写的项目少, 只是看文档时候产生的一点想法. 求大佬指正