I have an React Native app with two pages. On the first page I have a picker from which I need the data from in the second page. I try to use Context for making sate globally available but I didn't get it to work till now because I only get undefined types at the position where I wanna insert the global state and not the value who was selected from the picker. I dont't get any errors but the field where the picker value should be represented is empty.
File from which I wanna get state from:
const FirstFile = () => {
const [selectedValueRound, setSelectedValueRound] = useState("10 rounds");
return (
<View>
<RoundContext.Provider
value={[selectedValueRound, setSelectedValueRound]}
>
<View>
<Picker
selectedValue={selectedValueRound}
onValueChange={(itemValue, itemIndex) =>
setSelectedValueRound(itemValue)
}
>
<Picker.Item label="1 round" value="0"></Picker.Item>
<Picker.Item label="2 rounds" value="1"></Picker.Item>
</Picker>
</View>
</RoundContext.Provider>
</View>
);
};
Context file:
export const RoundContext = createContext(false);
Navigation file where I wrap my context around
const Stack = createNativeStackNavigator();
const {selectedValueRound, setSelectedValueRound} = useContext(RoundContext);
const MyStack = () => {
return (
<RoundContext.Provider value={[selectedValueRound, setSelectedValueRound]}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="FirsFile" component={FirsFile} />
<Stack.Screen name="SecondFile" component={SecondFile} />
</Stack.Navigator>
</NavigationContainer>
</RoundContext.Provider>
);
};
File where I try to insert the global value:
const SecondFile = () => {
const [selectedValueRound, setSelectedValueRound] = useContext(RoundContext);
return (
<View>
<Text>{selectedValueRound}</Text>
</View>
);
};
export default SomeFile;
CodePudding user response:
You also need to define context provider and wrap your app into it.
export const RoundContextProvider = ({children}) => {
const stateTuple = useState(false);
return <RoundContext.Provider value={stateTuple}>{children}</RoundContext.Provider>;
}
<RoundContextProvider>
<YourApp/>
</RoundContextProvider>
then you can use it as you described in the question: const [selectedValueRound, setSelectedValueRound] = useContext(RoundContext);
CodePudding user response:
You must declare the state
and the context provider in the top parent component. The children should only consume the values from the context.
The parent component
const MyStack = () => {
const [selectedValueRound, setSelectedValueRound] = useState("10 rounds");
const contextValue = useMemo(
() => [selectedValueRound, setSelectedValueRound],
[selectedValueRound]
);
return (
<RoundContext.Provider value={contextValue}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="FirsFile" component={FirsFile} />
<Stack.Screen name="SecondFile" component={SecondFile} />
</Stack.Navigator>
</NavigationContainer>
</RoundContext.Provider>
);
};
Note that I used useMemo
to prevent passing a new array to the context when selectedValueRound
did not change.
The children
const FirstFile = () => {
const [selectedValueRound, setSelectedValueRound] = useContext(RoundContext);
return (
<View>
<View>
<Picker
selectedValue={selectedValueRound}
onValueChange={itemValue => setSelectedValueRound(itemValue)}
>
<Picker.Item label="1 round" value="0"></Picker.Item>
<Picker.Item label="2 rounds" value="1"></Picker.Item>
</Picker>
</View>
</View>
);
};
const SecondFile = () => {
const [selectedValueRound] = useContext(RoundContext);
return (
<View>
<Text>{selectedValueRound}</Text>
</View>
);
};