javascript - React Context 不会更新所有子项

标签 javascript reactjs

我有两个组件使用 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>

最佳答案

每次使用 withUser 时,您都在创建一个新的 Provider

如果你想在整个应用中使用同一个用户,你可以将 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>

关于javascript - React Context 不会更新所有子项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55226481/

相关文章:

javascript - 我需要用该标签java脚本中的内容替换字符串中的<mark>标签

reactjs - React 文件上传返回未定义

javascript - HTML5 音频未在本地主机的 React 应用程序中播放

javascript - .click 不适用于更改选项卡容器的高度

javascript - IE8 array filter() 不起作用

javascript - 使用 Gulp Notify 和 Plumber 的全局错误消息

javascript - 在 React.js 和 React Native 应用程序之间重用代码

reactjs - 在 react 应用程序中创建首次访问弹出窗口?

javascript - React - 使用 wp_mail 发送电子邮件

javascript - 防止多次点击选中的单选框