Michael O'Connor
Michael O'Connor

Reputation: 141

React-native / redux - how to re-initialize screen via navigation?

I'm developing a react-native / redux app with a bottom-tab-navigator similar to the example at https://reactnavigation.org/docs/en/tab-based-navigation.html#customizing-the-appearance. My screens all connect to a Redux store and display shared data, however I'd like at least one of these screens to ignore the current data in the store and instead re-initialize this data each time it's navigated to (instead of continuing to display the data in whatever state it was last left in).

The screen has a method to do this, but I can't figure out how to call it after the first time the screen is rendered (e.g. from the constructor or componentDidMount() method). I can't call it from the render() method as this causes a "Cannot update during an existing state transition" error.

I need my navigator to somehow cause my HomeScreen.initializeData() method to be invoked each time the Home icon is pressed, but how do I do this?

HomeScreen.js:

initializeData() {
    this.props.resetData(initialValue);
}


const initialValue = ... 

(resetData() is a dispatch function that re-initializes the Redux store).

Upvotes: 2

Views: 774

Answers (2)

Michael O'Connor
Michael O'Connor

Reputation: 141

So I found an answer, it's a little more complicated than might be expected: As Vinicius has pointed out I need to use the tabBarOnPress navigation option, but I also need to make my dispatch function available to this navigation option.

To do this I found I need to pass a reference to my dispatch function (which is available as a property of my screen) into the navigation option, so I've used navigation params to do this and here's what I've ended up with:

HomeScreen.js:

componentDidMount() {
    initializeData(this.props);
    this.props.navigation.setParams({ homeProps: this.props });
}

export const initializeData = (homeProps) => {
    homeProps.resetData(initialValue);
};

const initialValue = ... 

AppNavigator.js:

tabBarOnPress: ({navigation, defaultHandler}) => {
    const routeName = navigation.state.routeName;

    if (navigation.state.params === undefined) {
        // no params available
    } else if (routeName === 'Home') {
        let homeProps = navigation.getParam('homeProps', null);
        initializeData(homeProps);
    } else if (routeName === ...
        ...
    }

    defaultHandler();
}

Notes:

  • I'm passing props as a navigation param rather than my dispatch function (which also works) as it's more flexible (e.g. it makes all of my dispatch functions available).
  • initializeData() is called both during construction of HomeScreen (for the first time the screen is displayed) and from the navigation icon (for subsequent displays of the screen).
  • It's necessary to check that params is defined within the navigation option as it'll be undefined the first time the screen is displayed (as screen construction has yet to occur). This also makes it necessary to call initializeData() during screen construction.

Upvotes: 0

Vinicius
Vinicius

Reputation: 1365

Updating state from render() would create an infinite loop. Also, you don’t want to run your state update every time the component re-render, only when the tab button is pressed. This tells me that the proper place to make your state update is some onPress function on the tab button.

So the question now relies on how to implement some onPress function on a tab button. I believe this answer this question: Is there an onPress for TabNavigator tab in react-navigation?

Upvotes: 1

Related Questions