react-navigation and component lifecycle

2019-06-26 00:36发布

问题:

I have a React Native application that uses react-navigation. In one of my screen, I'm using camera to read the QR code what works fine but I have to use setState({camera: false}) to prevent loading of QR code multiple times. Usually, it works. Even after re-entering page from main menu.

Trouble is when user press '<' button (iOS / in the header) and he should re-enter page with camera. I'm not able to find a function where I should do setState({camera: true}). Without react-navigation, there is standard lifecycle (componentWillMount, ...) but in this case I'm not able to find out where to put my code, so I can detect that page was re-entered.

I'm aware of https://github.com/react-community/react-navigation/issues/51 but I still miss the solution.

回答1:

I had a somewhat similar issue where i had screen A opens a screen B and i wanted to capture the event where i would come back to screen A from B.

My best guess was to send a callback from Screen A to B through the navigate function:

this.props.navigation.navigate("ScreenB",{
   onClose : ()=>{
      // update your state to open back the camera
   }
})

And then i needed to capture the closing event on Screen B, which basically was componentWillUnmount:

In ScreenB component class :

componentWillUnmount(){
   this.props.navigation.state.params.onClose()
}


回答2:

Currently, it looks like that there is not an elegant solution with react-navigation.

The best option is to use onNavigationStateChange (found at Screen Tracking page). In this function, we can detect that we are leaving the specified tab. If you plan to set data stored in redux then be aware that you will change the state => page will be rendered again and tab will not change. You have to handle changing the tab manually (e.g. via initialRouteName)



回答3:

Since people have already answered the correct React Native only approach I thought I might make a suggestion that saved me thousands of hours with these types of problems...

Why not use REDUX and set a globally accessible store variable to solve this? If you were using REDUX you could simply set once, that the camera is off and the global application state would not only remember this for you but also allow every component you have listening to the store, to now know the camera is not going to be firing on this screen. When the app is terminated or even when you set this value, if need be, you could persist to AsyncStorage and then retrieve it once the app opens and loads up.

This approach would be highly desirable as it does not require interfering with the intricacies of the RN-lifecycle. As soon as you start having to update or change encapsulated component state variables at specific times, or forcing it to update without wanting a render to happen, or forcing it to update during strange lifecycle events... you know you are taking a wrongful approach. At least that's what I have learned about my own work in RN.



回答4:

I agree with @GoreDefex (upvoted). Redux would probably be your best bet. Has a little learning curve but once your wire it in to your app it makes state management so much easier.

Especially if you are going to start having nested navigators such as a drawer navigator inside a stack navigator etc.