javascript - React Context 不会更新所有的孩子
问题描述
我有两个组件使用 HOC 从上下文提供程序获取数据。
然而,当一个孩子更新提供者中的状态时,它似乎并没有为所有使用 HOC 的组件更新,所以仍然显示旧值。
为什么会这样,或者我在这里做错了什么?如何获得所有组件的更新值?
Stack Snippet 的一个简单示例演示了该问题:
const { Component } = React;
const { render } = ReactDOM;
let UserContext;
const { Provider, Consumer } = (UserContext = React.createContext());
class UserProvider extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "Colin",
setName: this.setName,
};
}
setName = (name) => {
this.setState({name});
}
render() {
return <Provider value={this.state}>{this.props.children}</Provider>;
}
}
const withUser = Component => props => (
<UserProvider>
<Consumer>{user => <Component {...user} {...props} />}</Consumer>
</UserProvider>
);
const TempA = ({name}) => {
return <h1>A: {name}</h1>
}
const TempB = ({name, setName}) => {
return (
<React.Fragment>
<h1>B: {name}</h1>
<button onClick={() => setName('Ricardo')}>change name</button>
</React.Fragment>
)
}
const A = withUser(TempA);
const B = withUser(TempB);
const App = () => {
return (
<React.Fragment>
<A />
<B />
</React.Fragment>
)
}
const AppToRender = withUser(App);
render(<AppToRender />, document.getElementById('root'));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
解决方案
每次Provider
使用withUser
.
如果您想在整个应用程序中使用同一个用户,您可以将 放在组件Provider
的顶部,App
并且只需withUser
创建一个新的Consumer
.
const { Component } = React;
const { render } = ReactDOM;
const UserContext = React.createContext();
const { Provider, Consumer } = UserContext;
class UserProvider extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "Colin",
setName: this.setName,
};
}
setName = (name) => {
this.setState({name});
}
render() {
return <Provider value={this.state}>{this.props.children}</Provider>;
}
}
const withUser = Component => props => (
<Consumer>{user => <Component {...user} {...props} />}</Consumer>
);
const TempA = ({name}) => {
return <h1>A: {name}</h1>
}
const TempB = ({name, setName}) => {
return (
<React.Fragment>
<h1>B: {name}</h1>
<button onClick={() => setName('Ricardo')}>change name</button>
</React.Fragment>
)
}
const A = withUser(TempA);
const B = withUser(TempB);
const App = () => {
return (
<UserProvider>
<A />
<B />
</UserProvider>
)
}
render(<App />, document.getElementById('root'));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
推荐阅读
- vue.js - 传入可变 HTML 的 Vue 插槽
- javascript - Antd:需要更改折叠体的背景颜色
- javascript - Ajax - 将表格中的内容加倍
- outlook-addin - 对于代表联系人(.vcf)的项目附件,是否会有对应的MailboxEnums.AttachmentContentFormat
- visual-studio-2015 - 尝试将数据库引用添加到引用另一个数据库的数据库得到“没有这样的源”错误
- python - python replace not na value
- azure-cosmosdb - 如何使具有 2 个分区键的文档保持同步/参照完整性?
- formal-languages - Z 表示法:如何编写可以将一个或多个元组添加到关系的操作模式
- php - Load composer scripts inside class or function
- angular - 日期晚于今天日期时显示错误