react-native-router-flux: onEnter/onExit hooks inside scenes components

Is there any simple way to have onEnter / onExit hooks inside navigation scenes components? It’s very useful to have it because it gives the ability to create fancy animation effects.

At the moment I can see the only solution is passing props from root component and then process them inside componentWillReceivePropsof scenes component but it’s super-ugly. Maybe there is some easy way to handle it with callbacks, something like <Scene onEnter={() => this.sceneComponentRef.onEnter()} />?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 33 (16 by maintainers)

Most upvoted comments

@aksonov Can you provide a sample code using onEnter inside a component? Thanks

i’ve tried all suggestion here but failed, because my case is inside a tabs. recently i found solution from https://stackoverflow.com/questions/49005289/reload-screen-when-the-tab-is-changed to use didFocus listener. here is the code:

class YourComponent extends Component {
  componentDidMount() {
    this.didFocusListener = this.props.navigation.addListener(
      'didFocus',
      () => { console.log('did focus') },
    );
  }

  componentWillUnmount() {
    this.didFocusListener.remove();
  }

  render() {
    return ( /* your render */ );
  }
}

@luco it is not implemented yet, but it is not difficult to add, check sources (within createWrapper function), feel free to submit PR.

  render() {
    return (
      <Router>
        <Stack key="root">
          <Scene key="login" hideNavBar={true} component={LoginPanel} />
          <Tabs key="table" tabBarPosition='bottom' headerMode='screen' titleStyle={{ alignSelf: 'center' }}>
            <Scene key="TimeCard" onEnter={() => this.onEnter()} title='TimeCard' component={FirstScreen} />
            <Scene key="Joho" onEnter={() => this.onEnter()} title='Joho' component={MeisaiJoho} />
            <Scene key="Me" onEnter={() => this.onEnter()} title='Me' component={MePanel} />
          </Tabs>
          <Scene key="Change" component={MeisaiChange} />
          <Scene key="Me2" component={MePanel2} />
        </Stack>
      </Router>
    );
  }
  onEnter() {
    Actions.refresh({action:new Date().getTime()});
  }
  componentWillReceiveProps(nextProps: Readonly<P>, nextContext: any){
    console.log("FirstScreen ReceiveProps");
  }

This can be achieved refresh function, Actions.refresh ({action: new Date (). GetTime ()}); The value passed must be changed, otherwise it will not trigger the componentWillReceiveProps event Now I found that this method works only on android, ios does not work

This is starting to work for me after adding a static onExit method to my component.

I see ‘onExit’ in logs for both Android and iOS.

I am still trying to figure out how I can get to the component instance and component state from the component’s static onExit method?

        <Stack key="login" path="login/:data" titleStyle={{ alignSelf: 'center' }}>
          <Scene
            key="loginModal"
            component={Login}
            title="Login"
            onExit={() => { Login.onExit()}
            leftTitle="Cancel"
            onLeft={Actions.pop}
          />

Using:

		"react": "^16.2.0",
		"react-native": "^0.53.3",
		"react-native-router-flux": "4.0.0-beta.27",

@aksonov - I know you said that using componentDidMount is an anti-pattern, but it’s the only easy way right now to actually modify the navbar. I’m pretty sure other users are doing the following:

  • reading the state to determine if they should desplay: “edit” or “new” as a title
  • depending on the state - display “save” or “ready” buttons
  • the save button would call a function on the component that contains the logic to save, update the item

I’m actually thinking of completely giving up on the build-in navBar as it is too complicated to change the title and what the buttons do. Rendering a custom Navbar in each component looks like less work right now.

@aksonov can show me a example how to use Actions.refs.SCENE_NAME

Not sure if this will help but I solved this in my case where i wanted an api to be called every time i enter a screen that has already been mounted:

static onEnter() {
    if (Actions.refs.itemList !== undefined) {
        Actions.refs.itemList.selector.props.searchItems()
    }
}

Where searchItems is a redux action mapped using connect(mapStateToProps, {searchItems}) in the same component

Yoohooo! We have latest React Navigation release with exciting blur/focus events system. No more hacks and inconsistent onEnter/onExit behavior, we just need to adopt the new system to RNRF.

@aksonov Thanks a lot for recent onEnter / onExit as scene’s instances methods implementation. Unfortunately, onEnterbehavior is little bit of quirky - it works only when component is mounted(created first time), but when, for-example, a user navigates to already created scene, the scene is entered but onEnter is not invoked so it may be misleading… Hope what I’ve described makes sense… 😺

Same thing would be very useful for onLeft & onRight (onBack?) callbacks

@aksonov Thanks a lot for hint. Works great for onExit hook, but unfortunately, there is no component instance in Actions.refs yet on onEnter hook. Is there any workaround?

Yes, use Actions.refs.SCENE_NAME to refer to your component instance

You can try to use Actions.refs.SCENE_NAME to access component instance

@aksonov ( Yes, use Actions.refs.SCENE_NAME to refer to your component instance)

can you show me the code please? I still have no idea

You are right… Need to think how to implement it in better way…

if i have two same screen in my routestack,for example A B A C,when i back A from C, how can i discriminate which A i focus?

can i use define non-static onEnter/onExit methods now?