I was struggling with the same issue and tried some of the other answers before discovering the following part of the documentation for React Navigation: https://reactnavigation.org/docs/en/stack-navigator.html#params.
Essentially, each Screen in the Stack can be passed params which can include handlers and then the various screens can interact with the application state.
My general structure is then to have an App class with state and handlers and the handlers are then passed into each Navigation Screen as needed. I'm not sure if I have this pattern right, but it's the way I understood the general React tutorial.
Example: In my demo app, I have a page flow like this:
- Park finder screen -> Park detail screen (with
Bookmark action)
- Bookmark list screen -> Park detail screen
If you find a park, you can click on a Bookmark button which adds the park to the list of bookmarks shown on the Bookmark screen. You can then click on a park bookmark to see the details.
My App looks generally like this:
import React, { Component } from 'react';
// Screens
import ParkFinderScreen from './Components/ParkFinderScreen';
import ParkBookmarksScreen from './Components/ParkBookmarksScreen';
import ParkDetailsScreen from './Components/ParkDetailsScreen';
// Navigation
import { createStackNavigator, createBottomTabNavigator, createAppContainer } from 'react-navigation';
class App extends Component {
constructor(props) {
super(props);
this.state = {
bookmarks: new Map()
};
}
// Bookmark the park shown in the detail section.
handleBookmark (park) {
let newBookmarks = this.state.bookmarks;
newBookmarks.set(park.parkCode, park);
this.setState({
bookmarks: newBookmarks
});
}
render() {
const FinderStack = createStackNavigator(
{
ParkFinder: {
screen: ParkFinderScreen
},
ParkFinderDetails: {
screen: ParkDetailsScreen,
params: {
handleBookmark: (park) => this.handleBookmark(park),
}
},
}
);
const BookmarksStack = createStackNavigator(
{
ParkBookmarks: {
screen: ParkBookmarksScreen,
params: {
bookmarks: this.state.bookmarks
}
},
ParkBookmarksDetails: {
screen: ParkDetailsScreen,
},
}
);
const AppNavigator = createBottomTabNavigator(
{
Bookmarks: BookmarksStack,
Finder: FinderStack,
}
);
const AppContainer = createAppContainer(AppNavigator);
return (
<AppContainer/>
);
}
}
export default App;
I'm using Apollo Client, but I've removed those parts.
In the Screen components, you can access the props like other ones using this.props.navigation.getParam('bookmarks').
One issue I encountered was that whenever I change the App state, I'm taken to the first screen. The state is updated, but it's a little disorienting. I'm not sure if there is a way to update the App state while staying on the screen. I can sort of understand that given the App state has updated, all the children need to be updated and so the current screen (which is part of a child I think) is reset. I don't know if that is a limitation of the system or a byproduct of how I designed the components.
I hope this helps someone. This seems to keep with the intended behavior of React Native. The library team really seems to want you to not use Redux. https://reactnavigation.org/docs/en/redux-integration.html
HomeandTaskFormare sibilings. if you want one to modify the state in the other you need to have that state shared by a common ancestor, which in your case isPluralTodo. Presumably you can call theStackNavigatorfunction inside PluralTodo's render method to initialize your nav and pass any handlers / state there - aziumMain: {screen: props => <MainScreen yourProps={..} {...props} />}, - azium