【问题标题】:React Context API Seems to re-render every componentReact Context API 似乎要重新渲染每个组件
【发布时间】:2018-12-16 10:45:24
【问题描述】:

我正在尝试在我的应用程序中使用新的 Context API,看起来每次我更新上下文时,它都会重新渲染连接到它的任何组件。我有一个沙盒演示设置来查看代码和工作问题。当您输入输入时 - 呈现按钮上下文,反之亦然。我最初的想法是,如果您输入输入,则只会打印出输入上下文。

DEMO

这是它的工作原理还是我错过了什么? 谢谢, 斯宾塞

【问题讨论】:

  • 我不确定我是否正确理解了这个问题,但所有依赖于此上下文的组件都会重新呈现。它被称为主题上下文。如果您更新主题,您会期望所有主题组件都会更新。
  • 啊——好的。因此,如果我不希望在文本更改时重新渲染按钮,那么它们是否需要拥有自己的“CONTEXT API”?我来自 redux,所有东西都在商店里,当一个项目发生变化时,整个商店不会在每个连接的组件中传播 are-render。
  • 是的,不同的上下文。如果您需要对此类“商店”进行更多控制,Redux 可能是更好的选择。

标签: javascript reactjs react-context


【解决方案1】:

我避免使用 react context API 重新渲染的方式:

首先我把我的组件写成纯函数式组件:

const MyComponent = React.memo(({
    somePropFromContext,
    otherPropFromContext, 
    someRegularPropNotFromContext  
}) => {
    ... // regular component logic
    return(
        ... // regular component return
    )
});

然后我写了一个函数来从上下文中选择道具:

function select(){
  const { someSelector, otherSelector } = useContext(MyContext);
  return {
    somePropFromContext: someSelector,
    otherPropFromContext: otherSelector,
  }
}

我有我的连接 HOC 写道:

function connect(WrappedComponent, select){
  return function(props){
    const selectors = select();
    return <WrappedComponent {...selectors} {...props}/>
  }
}

大家一起

import connect from 'path/to/connect'

const MyComponent ... //previous code

function select() ... //previous code

export default connect(MyComponent, select)

用法

<MyComponent someRegularPropNotFromContext={something} />

演示

Demo on codesandbox

结论

MyComponent 仅当 context 中的 specifics props 更新为新值时才会重新渲染,如果值相同,则不会重新渲染。它还避免在MyComponent 中未使用的上下文中重新渲染任何其他值。每次上下文更新时,select 中的代码都会执行,但由于它什么都不做,没关系,因为不会浪费 MyComponent 的重新渲染。

【讨论】:

  • 这不违背 Context API 应该做的事情吗?还不如使用 Redux,因为您正在创建自己的“连接”功能......通过添加连接器仍然存在两个问题:Wrapper Hell 和 Props Drilling
  • 佩德罗斯之战
  • 给我错误:React Hook "..." 在函数 "select" 中被调用,它既不是 React 函数组件也不是自定义 React Hook 函数
  • @HasanSefaOzalp 你可能做错了什么,可能没有在你使用它的地方导入选择函数。
  • 这是一些解决方案,但没有回答问题。答案是无论如何它都不会将任何组件从提供者转移到消费者。
【解决方案2】:

这是预期的行为。当提供者数据更新时,作为消费者的组件会重新呈现。此外,shouldComponentUpdate 钩子不适用于消费者。

引用 React 的内容 API:

只要 Provider 的 value 属性发生变化,所有作为 Provider 后代的 Consumer 都会重新渲染。从 Provider 到其后代 Consumer 的传播不受 shouldComponentUpdate 方法的约束,因此即使祖先组件退出更新,Consumer 也会更新。

更多信息请查看here

【讨论】:

  • 谢谢 - 所以基于此 - 我必须需要第二个上下文 api,以便在文本更改时不会重新渲染按钮......
  • 或者你可以使用shouldComponentUpdate()钩子来决定是否需要重新渲染。这应该可以解决您的问题吧?
  • 好的,这确实有所帮助,但并没有完全达到我的预期,但这确实有助于解决很多问题。出于某种原因,我只是希望它更像 Redux。谢谢!
  • 我刚刚更新了我的答案。如果您认为我的回答是正确的,请随时接受它
  • 再次感谢。我最终在 redux 中编写它只是为了达到同一点哈哈。但是在深入了解上下文 API 的本质的过程中,我学到了很多东西。 ShouldComponentUpdate 在获得类似于 Redux 的行为渲染方面提供了巨大帮助——尽管 Redux 是免费的——但很高兴知道这一点。干杯
猜你喜欢
  • 2018-12-21
  • 2015-09-22
  • 2019-05-08
  • 1970-01-01
  • 2020-02-29
  • 2022-01-18
  • 1970-01-01
相关资源
最近更新 更多