首页 > 解决方案 > 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>

标签: javascriptreactjs

解决方案


每次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>


推荐阅读