来自库的反应上下文未在消费者中更新

Posted

技术标签:

【中文标题】来自库的反应上下文未在消费者中更新【英文标题】:React context from library not updating in consumer 【发布时间】:2020-11-25 19:01:11 【问题描述】:

我最初关注 this project 将 Firebase 添加到 Gatsby React 应用程序。它包括创建一个 Firebase 上下文,用提供者包装根布局,然后根据需要使用 withFirebase HOC 用 Firebase 消费者包装组件。当我最初这样做时,它运行良好,但我想将代码移动到一个可以在我的应用程序中重用的包中。这是 HOC

export const withFirebase = (Component) => (props) => (
  <FirebaseContext.Consumer>
    (firebase) => <Component ...props firebase=firebase />
  </FirebaseContext.Consumer>
);

每个页面都以一个 Layout 组件开始,该组件呈现:

<FirebaseContext.Provider value=this.state.firebase>
  <AppWithAuthentication>
    this.props.children
  </AppWithAuthentication>
</FirebaseContext.Provider>

AppWithAuthentication 本身使用 withFirebase HOC,因为它需要 Firebase 来获取 AuthUser(然后将其存储在上下文中并通过提供者传递),并且它能够很好地做到这一点。

以上所有情况都发生在包代码本身中,但是当我将包导入我的另一个 React 项目时,尝试使用 withFirebase 停止工作,因为任何用它包裹的组件都不会收到更新的上下文。我通过检查 React Dev 工具中的组件树来确认这一点,Firebase 提供程序获取更新的非空值,AppWithAuthentication 内部的消费者也得到它。但是我的实际应用程序中的消费者没有更新(我在同一个库中创建的 AuthUser 上下文也有同样的问题)。

我什至认为父级可能以某种方式使用更新的消费者进行渲染,但子级没有重新渲染,但是在计算渲染并记录它们之后,很明显我的应用程序中的组件渲染的次数比 @987654337 多@。为了更清楚一点,这是我的组件树(从页面根目录的 Layout 组件开始):

这里的 Provider 显示一个值:

这里是 AppWithAuthentication 的消费者显示值:

这是我的应用程序内部没有值的消费者:

我完全被困在这里,如果有任何见解,我将不胜感激。

编辑: 经过更多测试后,我发现了更多信息,但我仍然卡住了。似乎在重新加载我的页面时,Layout 组件渲染了 2 次,HeaderAppWithAuthentication 组件各渲染了 4 次,而 Login 组件仅渲染了 1 次。这就是消费者不更新的原因吗? (但是为什么Header 组件在更新与AppWithAuthentication 一样多时没有得到任何更新?)

编辑 2: 经过更多研究,我认为这个问题与webpack有关?我正在使用 Neutrino.js 来制作我的组件库,并将其构建的输出作为库。我发现this question 看起来很相似,并尝试在我的.neutrinorc.js 中实现修复:

const reactComponents = require('@neutrinojs/react-components');

module.exports = 
  use: [reactComponents(),
  (neutrino) => 
     neutrino.config.output.library("upe-react-components");
     neutrino.config.output.libraryTarget("umd");
     neutrino.config.mode("development");
    ],
;

但这并没有解决问题。有没有人遇到过 webpack 破坏 React 上下文的问题?

【问题讨论】:

【参考方案1】:

我从一个聪明的朋友那里听说问题是因为 React 上下文是在模块级别定义的,因此由于您尝试将上下文放在单独的入口点中,所以事情不会那么顺利。

我认为您可以尝试制作一个 index.js 文件来重新导入和导出所有内容,然后一切都应该正常工作,因为它们都合并到一个模块中。

【讨论】:

是的,最终暂时修复了它。我发现有一篇文章进一步描述了它:***.com/a/60655639/3325942我现在会接受这个答案,但我希望我能找到不同的解决方法,因为只有一个入口点会使导入变得更加混乱。

以上是关于来自库的反应上下文未在消费者中更新的主要内容,如果未能解决你的问题,请参考以下文章

在消费者之外更新反应上下文?

从消费者 componentDidMount 更新反应上下文会导致无限重新渲染

反应多个上下文

反应警告:失败的上下文类型:所需的上下文“路由器”未在“组件”中指定

如何在本机反应中模拟上下文消费者反应元素

如何将默认反应上下文值设置为来自 Firestore 的数据?