问题
MyContext.js
import React from "react";
const MyContext = React.createContext('test');
export default MyContext;
Created A context separate js file where i can access in my parent as well as my child component
Parent.js
import MyContext from "./MyContext.js";
import Child from "./Child.js";
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
Message: "Welcome React",
ReturnMessage:""
};
}
render() {
return (
<MyContext.Provider value={{state: this.state}}>
<Child />
</MyContext.Provider>
)
}
}
So created a parent component, with Provider context and calling child component in provider tab
Child.js
import MyContext from "./MyContext.js";
class Child extends Component {
constructor(props) {
super(props);
this.state = {
ReturnMessage:""
};
}
ClearData(context){
this.setState({
ReturnMessage:e.target.value
});
context.state.ReturnMessage = ReturnMessage
}
render() {
return (
<MyContext.Consumer>
{(context) => <p>{context.state.Message}</p>}
<input onChange={this.ClearData(context)} />
</MyContext.Consumer>
)
}
}
So in child by using consumer can display the in child render part..
I'm facing to update from consumer to provider state.
How to update provider state or manipulate state of provider ..
回答1:
Firstly, in order to update the context from the consumer, you need to access the context outside of the render function, For details on how to do this, check
Access React Context outside of render function
Secondly, you should provide a handler from Provider which updates the context value and not mutate it directly. Your code will look like
Parent.js
import MyContext from "./MyContext.js";
import Child from "./Child.js";
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
Message: "Welcome React",
ReturnMessage:""
};
}
updateValue = (key, val) => {
this.setState({[key]: val});
}
render() {
return (
<MyContext.Provider value={{state: this.state, updateValue: this.updateValue}}>
<Child />
</MyContext.Provider>
)
}
}
Child
import MyContext from "./MyContext.js";
class Child extends Component {
constructor(props) {
super(props);
this.state = {
ReturnMessage:""
};
}
ClearData(e){
const val = e.target.value;
this.setState({
ReturnMessage:val
});
this.props.context.updateValue('ReturnMessage', val);
}
render() {
return (
<React.Fragment>
<p>{this.props.context.state.Message}</p>}
<input onChange={this.ClearData} />
</React.Fragment>
)
}
}
const withContext = (Component) => {
return (props) => {
<MyContext.Consumer>
{(context) => {
return <Component {...props} context={context} />
}}
</MyContext.Consumer>
}
}
export default withContext(Child);
回答2:
Updating Context from a Nested Component
It is often necessary to update the context from a component that is nested somewhere deeply in the component tree. In this case you can pass a function down through the context to allow consumers to update the context:
theme-context.js
// Make sure the shape of the default value passed to
// createContext matches the shape that the consumers expect!
export const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: () => {},
});
theme-toggler-button.js
import {ThemeContext} from './theme-context';
function ThemeTogglerButton() {
// The Theme Toggler Button receives not only the theme
// but also a toggleTheme function from the context
return (
<ThemeContext.Consumer>
{({theme, toggleTheme}) => (
<button
onClick={toggleTheme}
style={{backgroundColor: theme.background}}>
Toggle Theme
</button>
)}
</ThemeContext.Consumer>
);
}
export default ThemeTogglerButton;
app.js
import {ThemeContext, themes} from './theme-context';
import ThemeTogglerButton from './theme-toggler-button';
class App extends React.Component {
constructor(props) {
super(props);
this.toggleTheme = () => {
this.setState(state => ({
theme:
state.theme === themes.dark
? themes.light
: themes.dark,
}));
};
// State also contains the updater function so it will
// be passed down into the context provider
this.state = {
theme: themes.light,
toggleTheme: this.toggleTheme,
};
}
render() {
// The entire state is passed to the provider
return (
<ThemeContext.Provider value={this.state}>
<Content />
</ThemeContext.Provider>
);
}
}
function Content() {
return (
<div>
<ThemeTogglerButton />
</div>
);
}
ReactDOM.render(<App />, document.root);
The above example is straight from the React Context API docs v16.8.6, and is the recommended way to update a context value from a consumer. https://reactjs.org/docs/context.html#updating-context-from-a-nested-component
回答3:
You need to write a function in the Provider component to update the State. To be exact Consumer can only use the values and the function(s) you wrote in the Provider component.
In Parent Component
updateReturnMessage = (ReturnMessage) => {
this.setState((prevState) => ({ ...prevState, ReturnMessage }))
}
<MyContext.Provider value={{ state: this.state, updateReturnMessage: this.updateReturnMessage }}>
// your code goes here
</MyContext.Provider>
In Child Component:
ClearData(e){
const val = e.target.value;
this.context.updateReturnMessage(val);
}
This function is similar to the action creators
available in Redux
and flux
回答4:
@nowshad, are you trying to use with redux Then I suggest using the provider
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
const store = createStore(todoApp)
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
If you are using for just few components and you want to have values for all nested components as per your statement
For nested components can i have one provider and multiple consumers For an Example : 1 is an parent , 1.1 is a child to 1 and 1.1.1 is child to 1.1, Can i have provider to 1 and consumers to 1.1 and 1.1.1
then I suggest that you just pass a handler down as prop and once you want to change the state call the handler and it will change values throughout your components.(This should be done if you have just few child components, who all require the same values throughout)
***Using context, we can avoid passing props through intermediate elements***
As per React Docs
Don’t use context just to avoid passing props a few levels down. Stick to cases where the same data needs to be accessed in many components at multiple levels.
Check Official Docs as to why and why not use Context: https://reactjs.org/docs/context.html
Let me know if you still have issues or doubts as to why and how to use context
来源:https://stackoverflow.com/questions/50502664/how-to-update-the-context-value-in-provider-from-the-consumer