来自库的反应上下文未在消费者中更新
React context from library not updating in consumer
我最初跟随 this project 将 Firebase 添加到 Gatsby React 应用程序。它涉及创建一个 Firebase 上下文,使用提供者包装根布局,然后使用 withFirebase HOC 根据需要使用 Firebase 消费者包装组件。当我最初这样做时,它运行良好,但我想将代码移动到一个包中,我可以在我的应用程序中重复使用。这是 HOC
export const withFirebase = (Component) => (props) => (
<FirebaseContext.Consumer>
{(firebase) => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
并且每个页面都以呈现此内容的布局组件开头:
<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 上下文也有同样的问题)。
我什至认为,也许父级正在使用更新后的消费者进行渲染,但子级并没有重新渲染,但是在计算渲染次数并记录它们之后,很明显我的应用程序中的组件渲染次数比AppWithAuthentication
。为了更清楚一点,这是我的组件树(从页面根部的 Layout 组件开始):
这是 Provider 显示的值:
这是 AppWithAuthentication
的消费者显示的值:
这是我应用程序内部的消费者, 没有值:
我完全被困在这里,非常感谢任何见解。
编辑:
经过更多测试后,我发现了更多信息,但我仍然卡住了。似乎在重新加载我的页面时,Layout
组件呈现 2 次,Header
和 AppWithAuthentication
组件各呈现 4 次,而登录组件仅呈现 1 次。这就是消费者不更新的原因吗? (但是为什么 Header
组件更新到 AppWithAuthentication
就没有更新?)
编辑 2:
经过更多研究,我认为这个问题与webpack有关?我正在使用 Neutrino.js 来制作我的组件库,并将其构建的输出作为库。我发现 看起来很相似,并尝试在我的 .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 上下文的问题吗?
我从我的一个聪明的朋友那里听说问题是因为 React 上下文是在 module-level 定义的,所以既然你试图将你的上下文放在单独的入口点,事情就不会那么顺利。
我认为您可以尝试制作一个 index.js 文件,该文件 re-imports 并导出所有内容,然后事情应该会正常进行,因为它全部合并到一个模块中。
我最初跟随 this project 将 Firebase 添加到 Gatsby React 应用程序。它涉及创建一个 Firebase 上下文,使用提供者包装根布局,然后使用 withFirebase HOC 根据需要使用 Firebase 消费者包装组件。当我最初这样做时,它运行良好,但我想将代码移动到一个包中,我可以在我的应用程序中重复使用。这是 HOC
export const withFirebase = (Component) => (props) => (
<FirebaseContext.Consumer>
{(firebase) => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
并且每个页面都以呈现此内容的布局组件开头:
<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 上下文也有同样的问题)。
我什至认为,也许父级正在使用更新后的消费者进行渲染,但子级并没有重新渲染,但是在计算渲染次数并记录它们之后,很明显我的应用程序中的组件渲染次数比AppWithAuthentication
。为了更清楚一点,这是我的组件树(从页面根部的 Layout 组件开始):
这是 Provider 显示的值:
这是 AppWithAuthentication
的消费者显示的值:
这是我应用程序内部的消费者, 没有值:
我完全被困在这里,非常感谢任何见解。
编辑:
经过更多测试后,我发现了更多信息,但我仍然卡住了。似乎在重新加载我的页面时,Layout
组件呈现 2 次,Header
和 AppWithAuthentication
组件各呈现 4 次,而登录组件仅呈现 1 次。这就是消费者不更新的原因吗? (但是为什么 Header
组件更新到 AppWithAuthentication
就没有更新?)
编辑 2:
经过更多研究,我认为这个问题与webpack有关?我正在使用 Neutrino.js 来制作我的组件库,并将其构建的输出作为库。我发现 .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 上下文的问题吗?
我从我的一个聪明的朋友那里听说问题是因为 React 上下文是在 module-level 定义的,所以既然你试图将你的上下文放在单独的入口点,事情就不会那么顺利。
我认为您可以尝试制作一个 index.js 文件,该文件 re-imports 并导出所有内容,然后事情应该会正常进行,因为它全部合并到一个模块中。