Share state between navigation buttons and main view

React navigation is the suggested community package for navigation in React native apps. It has three navigators: Stack navigator, Tab navigator and Drawer navigator. There are quite a few configuration options. Overall, I find it quite useful for my needs. But, there is one area that requires a bit of work. It is about sharing data between the navigation buttons and the main app view.

Static navigationOptions

Let me show you why it is difficult with some code. We specify the Next button in navigation options of our component.

class OTPVerification extends React.Component {
  static navigationOptions = {
    headerRight: <Button title="Next" />
  };

  ...
}

NavigationOptions is a static property on the component. This means it cannot access props or state using “this”.

Moving state to Redux

For our example, we are putting together an OTP screen. When the user types in 6 digits, the Next button should be enabled. How do we share the OTP between the main app view and the navigation button? I am going to present a solution using Redux in this article. But you are free to use any state management container as you please. The solution is to place the OTP in a global state.

<TextInput onChangeText={this.props.onOTPChange} />

onOTPChange is mapped to a redux action, changeOTP.

export default connect(null, { onOTPChange: changeOTP })(OTPVerification);

changeOTP is a simple action creator which passes the OTP to the reducer.

function changeOTP(otp) {
  return {
    type: 'CHANGE_OTP',
    otp
  };
}

The OTP reducer updates the otp information.

function otpReducer(state = {}, action) {
  switch(action.type) {
    case 'CHANGE_OTP':
      return {
        ...state,
        otp: action.otp
      };
    default:
      return state;
  }
}

Use state from Redux

Now, that we got the OTP in global state, our Next button is capable of using it.

class NextButton extends React.Component {
    render() {
        return (
            <Button
                title="Next"
                disabled={this.props.otp.length !== 6}
                onPress={this.props.onLoginVerify}
            />
        );
    }
}

const NextButtonWrapper = connect(
    state => ({
        otp: state.otp.otp || ''
    }),
    { onLoginVerify: verifyLogin }
)(NextButton);

Redux connect wraps the NextButton with props. The button gets the OTP from the global state. It also gets an additional callback function to verify the login.

class OTPVerification extends React.Component {
    static navigationOptions = {
        headerRight: <NextButtonWrapper />
    };

Redux allows to share state between the main app view and the navigation buttons. This is a pattern that I have repeatedly used within my apps when working with react-navigation.

Related Posts

Leave a Reply

Your email address will not be published.