如何用反应钩子完全替换redux?

Posted

技术标签:

【中文标题】如何用反应钩子完全替换redux?【英文标题】:How to completely replace redux with react hooks? 【发布时间】:2021-05-07 22:32:36 【问题描述】:

我正在考虑使用 react hooks [useReducer, useContext] 和 context api 来代替 redux。话虽如此,我希望我的状态在结构上有点复杂。让我们看看结构是这样的

state = 
    key1: true,
    key2: 
        key3: [],
        key4: ''
    

我很清楚的是 redux 和 context api 都允许我创建复杂的结构。在使用 react hooks 的情况下,我可以很好地使用 Provider、Consumer/useContext 将我的商店状态值传递给我的所有组件。

Redux 给我的更多信息是,如果更新了任何特定的键 key4,则可以帮助我不要使用来自 react-redux 的连接函数重新渲染整个应用程序树。这是我的查询。

我们如何使反应钩子和上下文 API 不重新渲染我的整个应用程序,这是一个主要的性能错误?

【问题讨论】:

【参考方案1】:

这是您仅通过反应上下文无法实现的。当然,您可以使用 useMemo 进行欺骗,以便您的 Provider 的直接子代不会重新呈现,但除此之外:每当您的上下文值的任何属性发生变化时,所述上下文的所有消费者都将重新呈现,无论他们是否使用了那个特定的财产与否。您不能只为某些孩子放弃上下文重新渲染。

一旦useContextSelector 被集成到 react 中,这可能会在未来发生变化,但目前,这只是标准的 React 行为,没有办法解决。

您可以找到有关“上下文与真实状态管理解决方案”in this article 的更多信息。

目前,如果您只是想减少样板文件,最好阅读 modern redux 或查看其他成熟的状态管理库,如 mobx 或 recoil。但是,如果不完全重新实现其中之一,您将无法仅凭上下文到达那里 - 那有什么意义呢?

【讨论】:

作为刚开始学习 React 的人,您链接的文章非常有用。我目前正在使用 Context + useReducer 来管理状态,但是随着我正在开发的应用程序增加了越来越多的复杂性(我有 5 个与状态相关的上下文),开始查看 Redux 可能是个好主意。 @Mike 如果您开始使用 redux,请按照redux.js.org/tutorials/index 的官方教程进行操作 - 这些都是最新的,而许多其他资源(甚至是最近发布的)都已经过时了约会并弄错几个最佳实践。 请记住这一点。我目前正在通过udemy.com/course/react-redux,但我还没有进入 Redux 部分。我想我应该在观看视频之前先阅读官方教程。 我非常赞同使用 redux 进行状态管理。但是在应用程序中,人们建议使用 apollo gql 进行状态管理,它适用于反应钩子的概念,这就是为什么我开始寻找方法让所有状态成为复合状态,就像我们在 redux 中所做的那样,因为重新渲染触发器但想通了当我想到设计时,就解决了这个问题。这可能很烦人,但我们是否有任何第三方库可以按照我的要求做同样的事情? 我的意思是在我的应用程序中我们没有使用 redux 来维护状态。我的话不好。【参考方案2】:

re-rendering 组件树是 react 管理得很好的事情。 redux 和 context api 都会更新组件状态,这会导致重新渲染。在性能方面,如果您正在寻找一种方法来管理不必要的重新渲染,我建议您查看一些有用的钩子,useMemouseCallbackReact.memo

通过这三个钩子,您可以防止子组件在父组件更新时重新渲染。

const Parent = () => 

  const [childAState, setChildAState] = useState();

  useEffect(() => 
    setChildAState('Child A Updated');
  , []);
  
  return (
    <ChildA childAState=childAState/>
    <ChildB />
  );

;

const ChildA = () => React.memo((props) => 

  return <h1>Child A</h1>  

);

const ChildB = () => React.memo((props) => 

  return <h1>Child B</h1>  

);

在上面的示例中,如果Parent 中的状态发生变化并导致ChildA 中的更新,ChildB 将不会重新渲染。

进一步阅读:React.memo

【讨论】:

但仍然触发从上到下重新渲染不是我们应该做的事情,这是我想要避免的。 你无法避免重新渲染。实际上,在每个状态更改时,react 都会重新渲染所有组件树,这取决于更新的组件。您可以通过控制重新渲染和不重新渲染的内容来优化它。【参考方案3】:

如果你真的想用 hooks 替换 Redux,我建议使用 useReducer 和 useContext hooks,它们很容易理解并且相当灵活,这里有一篇文章比较了 Redux 和 React hooks 和细节: https://www.framelessgrid.com/react-hooks-vs-redux-for-state-management-in-2021/

【讨论】:

以上是关于如何用反应钩子完全替换redux?的主要内容,如果未能解决你的问题,请参考以下文章

组件不会重新渲染,但 redux 状态已通过反应钩子更改

React Hooks 与 React-redux

来自 Redux 存储的数据来晚了,所以它不会填满 AG 网格表/反应钩子

如何用酶测试反应路由器

试图在反应 redux 中包装调度功能

如何用自定义字符串完全替换 pytest 输出以进行测试?