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

Created on 28 Aug 2017  Â·  33Comments  Â·  Source: aksonov/react-native-router-flux

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()} />?

enhancement help wanted

Most helpful comment

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

All 33 comments

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

@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?

Is there a way to change state and props of rendered component with onEnter/onExit? Currently i can only read pros and state with onExit/onEnter hook using Action.refs.SCENE_NAME @aksonov

@todorone, @Megamind2301 It could be good enhancement - ability to define non-static onEnter/onExit methods.

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

@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.

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

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

It will be more difficult for onLeft/onRight/onBack - you could just use Actions.refs.SCENE_NAME to access your component

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

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?

with the same problem with @Tomatoo ,My routestack is A->A->A->A->A,with different programs,but the Actions.refs just have one instance with A,So I doesn't know which A pop and Which Enter.

@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... 😺

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

@aksonov Btw, fixed onExit which is never invoked right now - #2759

Thanks, but please also run npm run build to recompile ES5-sources too.

@aksonov Sorry, missed it. #2760

@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

@aksonov Pretty good news. At last, lifecycle events system is currently being implemented in react-navigation so hopefully, with next release, we can reimplement onEnter/onExit hooks in more reliable and elegant way.
https://github.com/react-navigation/react-navigation/pull/3345

  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()});
  }



md5-3c7a5964f8b818ccf6d97a662c549184



  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

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.

Really good news, finally we could release v4 without beta too, does anyone have time to write PR, it should not be difficult I guess...

On 8 Feb 2018, at 09:39, Todor1 notifications@github.com wrote:

Yoohooo!
We have latest React Navigation release with exciting blur/focus events system - react-navigation/react-navigation#3345 https://github.com/react-navigation/react-navigation/pull/3345
No more hacks and inconsistent onEnter/onExit behavior, we just need to adopt the new system to RNRF.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/aksonov/react-native-router-flux/issues/2298#issuecomment-364040172, or mute the thread https://github.com/notifications/unsubscribe-auth/ABQpcXkpsXs5iPrZbbziRMtfnecV336mks5tSrK4gaJpZM4PE5OG.

When is it released? onEnter={() => this.onEnter()}Why is it working fine in android, but not in ios?
@aksonov

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",

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

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

@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

@JonathanLouw Thanks!! This also work for me. In my case the object structure was a bit different the what you're showing here but work it! Thanks one more time!

I think about this questions,use redux can fix all of them

@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

I spent 5 hours trying to solve this problem and your solution is the only one which worked. The only change I made is putting that code into the onEnter prop of the Scene, here is my code:

<Scene key="careers" component={Careers} onEnter={() => { if (Actions.refs.careers !== undefined) { Actions.refs.careers.selector.props.fetchCareersList(); } }} />

@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

Thank you my friend! You saved my day. For me it worked perfectly!

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 */ );
  }
}

any working code example please ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wootwoot1234 picture wootwoot1234  Â·  3Comments

kirankalyan5 picture kirankalyan5  Â·  3Comments

sylvainbaronnet picture sylvainbaronnet  Â·  3Comments

fgrs picture fgrs  Â·  3Comments

YouYII picture YouYII  Â·  3Comments