React Context不会更新所有子级

时间:2019-03-18 17:00:46

标签: javascript reactjs

我有两个组件,它们使用HOC从上下文提供程序获取数据。

但是,当一个孩子更新提供者中的状态时,似乎并没有为所有使用HOC的组件更新,因此仍然显示旧值。

为什么会这样,或者我在这里做错了什么?如何获取所有组件中的更新值?

一个用于说明问题的简单示例的堆栈摘录:

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>

1 个答案:

答案 0 :(得分:2)

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

如果您想在整个应用程序中使用同一用户,则可以将Provider放在App组件的顶部,而只需withUser创建一个新的{{1 }}。

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'));