I'm developing a Mobile Application using React Native. There, I'm passing something when navigating to the second page.
So, assume my first screen has something like this.
export default function firstScreen(props) {
return(
//data is a custom object variable that may be changed.
<Button onPress={() => props.navigation.navigate('SecondScreen', { data: data } )} />
)
}
On my second screen, assume there is something like this...
export default function secondScreen(props) {
const { data } = props.navigation.state.params;
useEffect(() => {
console.log(data);
}, [data])
return(
//content
)
}
My problem is, when data
is changed from the first screen, the second screen does not listen to that change and print the content of the data
variable on the console.
So, I want to know, how to listen to the navigation state changes in React Native.
You can use the hook 'useNavigationState' to get the navigation state from the second screen.
Then again you will have the problem of actually updating it from the first screen. When you pass a parameter its part of the navigation state and the changes you to do the object you have wont be reflected there.
One way to update navigation state would be to dispatch an action, but that will be a problem because you need to find the key of the screen you are going to update. the dispatch would be something like this
navigation.dispatch({ ...CommonActions.setParams({ data: {} }), source: route.key, });
As you have the need to get the updates of your object to another screen you should consider something like react context or if you already have redux in your app you can utilize that if the need is there.
Easiest way would be the react context which you can update from one screen and receive from another.
The version of using context would be like below. Here a simple stack navigator is used and the context is updated from home screen and the value can be read from settings screen. You can use the same way to update the data variable and get the data from the other screen. Here we dont use the navigation state but we maintain our own context for the variable.
const Stack = createStackNavigator();
const CountContext = React.createContext({ count: 1, setCount: () => {} });
function HomeScreen({ navigation, route }) {
const { count, setCount } = React.useContext(CountContext);
React.useEffect(() => {
const interval = setInterval(() => {
setCount(count => count + 1);
}, 1000);
return () => {
clearInterval(interval);
};
}, []);
return (
<View>
<Text>Test{count}</Text>
<Button
title="Go to settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen({ navigation, route }) {
const { count, setCount } = React.useContext(CountContext);
return (
<View>
<Text>Settings! {count}</Text>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
export default function App() {
const [count, setCount] = React.useState(0);
const value = { count, setCount };
return (
<CountContext.Provider value={value}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
</CountContext.Provider>
);
}
You can check out this snack https://snack.expo.io/@guruparan/stateparamschange