Home > Blockchain >  Get only undefined value from my global variable configured with Context
Get only undefined value from my global variable configured with Context

Time:05-22

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>
  );
};
  • Related