I may be misunderstanding how react context work in general, but how I think it should work goes like this:
I have a main app that has the Context provider as following
export default function app(){
return <contextObj.Provider value={Complex Object with multiple properties...}>
<Main/>
</contextObj.Provider>
}
My main app is as follows
export default function main(){
//Have imported the context class and am using it
let store = React.useContext(myContext)
return <React.Fragment>
<comp1 max={store.valueX} />
<comp2 />
</React.Fragment>
}
Inside of comp2, modify valueX inside of the context objext
export default function comp2(){
//Have imported the context class and am using it
let store = React.useContext(myContext)
return <buttonComp onClick={()=>store.valueX=3} />
}
So in theory comp1 should receive the updated value and re-render? This is where I'm stuck, as altering the context property isn't causing my comp1 to re-render.
Just like normal component state, you can't just directly mutate (assign to) the value of the context. You'll need to contain the value in state and pass down a callback to change that state (or use useDispatch
for example):
export default function App() {
const [value, setValue] = useState({
/* Complex Object with multiple properties */
});
const updateX = (newX) =>
setValue((prevValue) => {
return { ...prevValue, valueX: newX };
});
return (
<contextObj.Provider value={{ ...value, updateX }}>
<Main />
</contextObj.Provider>
);
}
export default function Comp2() {
//Have imported the context class and am using it
let store = React.useContext(myContext);
return (
<ButtonComp
onClick={() => {
store.updateX(3);
}}
/>
);
}
You'll probably want to move the state and the callbacks into a component specifically made for this - e.g. MyContextProvider
which just contains the state and wraps its children in MyContext.Provider
.
export function MyContextProvider({ initialValue, children }) {
const [value, setValue] = useState(initialValue);
const updateX = (newX) =>
setValue((prevValue) => {
return { ...prevValue, valueX: newX };
});
return (
<MyContext.Provider value={{ ...value, updateX }}>
{children}
</MyContext.Provider>
);
}
export default function App() {
return (
<MyContextProvider
initialValue={/* Complex object with multiple properties */}
>
<Main />
</MyContextProvider>
);
}
However, if you're deriving your complex object with multiple properties inside App
, it may be easier to just use the Context.Provider
directly like in my first example.
Also, remember to always capitalize your components' names:
Note: Always start component names with a capital letter.
React treats components starting with lowercase letters as DOM tags. For example,
<div />
represents an HTML div tag, but<Welcome />
represents a component and requiresWelcome
to be in scope.To learn more about the reasoning behind this convention, please read JSX In Depth.