All the documentation and blog posts I've managed to find so far only deals with a single [value, setValue] pair scenario. In my case I would like/need to pass multiple pairs of [value, setValue] variables to a Provider using the useContext hook.
Here is the typical example I setup in CodePen: https://codepen.io/nardove/pen/XWrZRoE?editors=0011
const App = () => {
return(
<div>
<MyProvider>
<ComponentA />
</MyProvider>
</div>
);
}
const MyContext = React.createContext();
const MyProvider = (props) => {
const [value, setValue] = React.useState("foo");
return(
<MyContext.Provider value={[value, setValue]}>
{props.children}
</MyContext.Provider>
);
}
const ComponentA = () => {
const [value, setValue] = React.useContext(MyContext);
return(
<div>
<h1>
The value is: {value}
</h1>
</div>
);
}
ReactDOM.render(<App /> , document.getElementById('app'));
If you can share any ideas on how pass multiple [value, setValue] pairs to the Provider or an alternative to my problem will be much appreciated
To pass multiple values in React Context, we can use the Provider API. Also, we can easily consume the context data by utilizing the useContext React Hook. However, it is important to understand the basic syntax and approach behind this. To get a better idea, let us look at a simple example.
To keep context re-rendering fast, React needs to make each context consumer a separate node in the tree. If two or more context values are often used together, you might want to consider creating your own render prop component that provides both.
You can use an aspect of es6 destructuring to rename the diff context object properties right inside your component. Like this: const { user, despatch: setUser } = useContext(UserContext); const { theme, despatch: setTheme } = useContext(ThemeContext); const { state, despatch: setState } = useReducer(reducer);
Context.Provider
accepts any value, so you can try passing an object:
<MyContext.Provider value={{ value: [value, setValue], value2: [value2, setValue2] }} > {props.children} </MyContext.Provider>;
const App = () => { return ( <MyProvider> <ComponentA /> </MyProvider> ); }; const MyContext = React.createContext(); const MyProvider = props => { const [value, setValue] = React.useState("foo"); const [value2, setValue2] = React.useState("goo"); return ( <MyContext.Provider value={{ value: [value, setValue], value2: [value2, setValue2] }} > {props.children} </MyContext.Provider> ); }; const ComponentA = () => { const { value, value2 } = React.useContext(MyContext); const [stateValue, setStateValue] = value; const [stateValue2, setStateValue2] = value2; return ( <div> <h1>The value is: {stateValue}</h1> <h1>The value2 is: {stateValue2}</h1> </div> ); }; ReactDOM.render(<App />, document.getElementById("app"));
Notice that there is a caveat when trying to optimize useless renders (be sure you not just optimizing prematurely): there is no render bailout for Context Consumers.
As for v17, may be change in near future.
To pass in multiple state values to a provider, you just need to create another state object and pass it in.
But inlining these comes with a caveat mentioned in the docs. Since the object (and arrays) in render are created every render, they lose the referential equality and hance any components connected to this context will need to refresh.
To get around this in a functional component, you can use useMemo
to memoise the value and refresh only when one of these values change.
const MyContext = React.createContext();
const MyProvider = (props) => {
const [valueA, setValueA] = React.useState("foo");
const [valueB, setValueB] = React.useState("bar");
const providerValue = React.useMemo(() => ({
valueA, setValueA,
valueB, setValueB,
}), [valueA, valueB]);
return(
<MyContext.Provider value={providerValue}>
{props.children}
</MyContext.Provider>
);
}
You can send values as shown below. I have sent demo1, setdemo1, demo2, and setdemo2. Inside the {{}} inside exportValues.provider It worked for me
import {View, Text} from 'react-native';
import React, {createContext, useState} from 'react';
export const exportValues = createContext();
const ContextTab = ({children}) => {
const [demo1, setdemo1] = useState([]);
const [demo2, setdemo2] = useState([]);
return (
<exportValues.Provider
value={{demo1, setdemo1,demo2, setdemo2}}>
{children}
</exportValues.Provider>
);
};
export default ContextTab;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With