Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting dynamic screen title based on redux state #940

Closed
tmaly1980 opened this issue Apr 6, 2017 · 13 comments
Closed

Setting dynamic screen title based on redux state #940

tmaly1980 opened this issue Apr 6, 2017 · 13 comments

Comments

@tmaly1980
Copy link

tmaly1980 commented Apr 6, 2017

I'm looking to customize a component's title depending on the state in redux, ie show "Sign In" if the user is not logged in (and render() will return a component). Unfortunately, all I have access to is the navigation state, and I don't pass along any user state to the navigate().

For the time being, I have:

Class OrdersContainer extends Component {
  static navigationOptions = {
      title: (navigation) => {
        return navigation.state.params.title || "Your Orders"
      }
    }

    setTitle()
    {
      const title = this.props.userProfile ? "Your Orders" : Login.navigationOptions.title;
      props.navigation.setParams({title: title});
    }

    componentDidMount() {
      this.setTitle();
    }

    componentWillUpdate()
    {
      this.setTitle();
    }

    render() {
      if(!this.props.userProfile) { return (<Login {...this.props}/>) } // Prompt for login if needed
      // .... normal content
    }

  } 

function bindActions(dispatch) {
    return bindActionCreators(ActionCreators,dispatch);
}

const mapStateToProps = state => ({
  userProfile: state.users.userProfile
});

export default connect(mapStateToProps, bindActions)(DealVault);

This unfortunately causes an infinite loop. I'm tempted to wrap mapStateToProps that also calls props.navigation.setParams.

UPDATE: Unfortunately, even wrapping mapStateToProps, props.navigation.setParams() cannot be called as the state is being changed. Assigning statically to props.navigation.state unfortunately doesn't refresh the title.

@pvinis
Copy link

pvinis commented Apr 12, 2017

@hlandao can you give the whole example? where is the state coming from, the one you assign to reduxstate?

@hlandao
Copy link

hlandao commented Apr 12, 2017

@pvinis

here you go: I'm wrapping each one of the components in a redux container:
in the example I'm wrapping the left & right views, but you can do the same for the title.

  1. Navigation options in my "screen" React component
  static navigationOptions = {
    header: (navigation) => {
      return {
        style: {    position: 'absolute',
          backgroundColor: 'transparent',
          zIndex: 100,
          top: 0,
          left: 0,
          right: 0
        },
        left: (<NotificationsButton />),
        right: (<DrawerButton />),
      }
    },
  };
  1. The Redux wrapped DrawerButton
...
const DrawerButton = ({iconsStyle, openDrawer}) => {
...
  return (
    <TouchableOpacity  style={styles.buttonTouchable} onPress={() => openDrawer()}>
      <Image source={settingsImageSource} style={styles.settingsImage}/>
    </TouchableOpacity>
  )
}

// REDUX MAPPING
const mapState = state => ({
})

const mapDispatch = dispatch => ({
  openDrawer: () => {
    const navigateAction = NavigationActions.navigate({
      routeName: DRAWER_OPEN
    })
    dispatch(navigateAction);
  }
})

export default connect(mapState, mapDispatch)(DrawerButton);

@lorenzsell
Copy link

@tmaly1980 - did you ever figure this out? I'm struggling with the same issue.

@tmaly1980
Copy link
Author

tmaly1980 commented Apr 21, 2017 via email

@lorenzsell
Copy link

@tmaly1980 @hlandao - this method only seems to kind of work for me. I can see the reduxState getting passed to navigationOptions, but unless I explicitly update the state.params, the title itself does not update. So I set title = reduxState.title and nothing happens. But if I call setParams with any kind of dummy data, title = reduxState.title does indeed update.

Am I missing something here?

@spencercarli
Copy link
Member

Hi! Since this issue has been quiet for a while I'm going to go ahead and close it. If the issue persists in the latest version of React Navigation please re-open!

@SimonVuong
Copy link

I was no longer able to get this to work as of 1.0.0-beta.22. so using screenProps instead

@arindam89
Copy link

Same here. I want to update the menu items in the contentComponent based on whether the customer is admin or not. I am unable to get this to work with connect() on contentComponent

@nicoladj77
Copy link

@SimonVuong how are you using screenProps?

@nickblt
Copy link

nickblt commented Feb 15, 2018

I solved this by wrapping Text within a connect call and passing the text to the children prop. A little funky but it works for my use case.

navigationOptions = {
  headerTitle: connect((state) => ({ children: getWhateverTitle(state) }))(Text),
}

@KianooshSoleimani
Copy link

its really simple you can make stateless component and connect it with redux like this :

 const view = ({ state, color }) => 
 {
   <View>
      <Text>{state.something}</Text>
   </View>
 }

export default connect(
    (state) => ({
       data: state.data,
    }),
    null
  )(view);

and then use it in static options :

  static navigationOptions = ({ navigation }) => {
      return {
          tabBarIcon: ({ tintColor }) => <view color={tintColor}/>
      }
  };

@EricWiener
Copy link

Please see this answer for an easier way to do this: https://stackoverflow.com/a/51883306/6942666

@Benzer1406
Copy link

Try using headerTitle: ... instead of title:... this solved my issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests