简体   繁体   中英

React Context API, updating context

I would like to set the context at runtime after some networking call is complete (only then do I know the value which needs to be accessible throughout my app), but I don't know how to persist this value.

I can update the context value like so:

<NetworkVersion.Provider value={{version: this.state.version}}>

where I can use the state of the component. This approach has been taken from the official React docs.

but I was surprised to find out that other Consumers of this Provider get the default value (an empty object) which was initialised in the React.createContext() call. Is there a way to update the Context at runtime and keep that value for the lifetime of the app?

Make sure your Context Consumer is a child of the associated Provider, otherwise it will just get the default value. See https://reactjs.org/docs/context.html#consumer

You'd also be better to pass a primitive value - ie

<NetworkVersion.Provider value={this.state.version}>

or you may get unnecessary re-renders. See https://reactjs.org/docs/context.html#caveats

A consumer must be a child of the provider to get the context. If it is impossible to make your consumer be a child of the provider, make a common parent be the provider and add a callback to the context to give consumers a possibility to change the context.

 const NetworkVersion = React.createContext({ version: null, setVersion: version => {} }); class Parent extends React.Component { state = { networkContext: { version: null, setVersion: version => this.setState({ networkContext: {...this.state.networkContext, version} }) } }; render() { return <NetworkVersion.Provider value={this.state.networkContext}> <VersionGetter/> <VersionSetter/> </NetworkVersion.Provider>; } } function VersionGetter() { return <NetworkVersion.Consumer> {networkContext => ( <div>Version: {networkContext.version}</div> )} </NetworkVersion.Consumer>; } function VersionSetter() { return <NetworkVersion.Consumer> {networkContext => ( <div> <button onClick={() => networkContext.setVersion('1.0')}>Set version 1</button> <button onClick={() => networkContext.setVersion('2.0')}>Set version 2</button> </div> )} </NetworkVersion.Consumer>; } ReactDOM.render(<Parent/>, document.body); 
 <script src="https://cdn.jsdelivr.net/npm/react@16.4.1/umd/react.production.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/react-dom@16.4.1/umd/react-dom.production.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM