I have a simple React component named Child
which increments its count when clicked. Also, an outside state is saved which get updated when the Child
component is incremented.
const Child = ({ onChange }) => {
const [count, setCount] = useState(0);
return (
<div>
<h1
onClick={() => {
setCount(prev => prev 1);
onChange(1);
}}
>
Child count = {count}
</h1>
</div>
);
};
const App = () => {
const [count, setCount] = useState(0);
return (
<div className="App">
<h1> Parent Count = {count} </h1>
<Child onChange={(i) => setCount(count i)} />
</div>
);
}
Above code works as expected. However, when I use the Context API to manage the outside state, the Child
component's internal count remains at 0
.
const App = () => {
const [count, setCount] = useState(0);
const AppContext = React.createContext();
return (
<div className="App">
<AppContext.Provider value={{ state: count, setState: setCount }}>
<>
<AppContext.Consumer>
{({ state }) => <h1> Parent Count = {state} </h1>}
</AppContext.Consumer>
<AppContext.Consumer>
{({ state, setState }) => (
<Child onChange={(i) => setState(state i)} />
)}
</AppContext.Consumer>
</>
</AppContext.Provider>
</div>
);
};
Sample CodeSandbox.
Why the internal state of the element inside AppContext.Provider
always reset to its initial state?
CodePudding user response:
First, the creation of a context should be outside of a Component, which means this line:
const AppContext = React.createContext()
should be outside of App
. Second, a context setup can be simpler, as below (I separated each component in its own file, so it resembles to common use cases), and working forked CodeSandbox here.
App:
import { useState, createContext } from "react";
import Child from "./Child";
export const AppContext = createContext();
const App = () => {
const [count, setCount] = useState(0);
return (
<div className="App">
<h1> Parent Count = {count} </h1>
<AppContext.Provider value={{ state: count, setState: setCount }}>
<Child />
</AppContext.Provider>
</div>
);
};
export default App;
Child:
import { useContext, useState } from "react";
import { AppContext } from "./App";
const Child = () => {
const { state, setState } = useContext(AppContext);
const [count, setCount] = useState(0);
return (
<div>
<h1
onClick={() => {
setCount((prev) => prev 1);
setState(state 1);
}}
>
Child count = {count}
</h1>
</div>
);
};
export default Child;