Reputation:
I have two screens: A and B, connected with a StackNavigator
Screen A is a QR code scanner. As soon as a QR code is scanned, it navigates to screen B.
In screen B, I make an API call using the QR code that gets passed as a navigation param from screen A. I trigger this API call in componentDidMount.
My issue is: if I navigate from A to B, then back to A, then to B again, componentDidMount does not get called and I have no way to trigger the API call.
Here's some code
Screen A
Handler function that gets called when a QR code is scanned:
handleQRCode = qrCode => {
NavigationService.navigate('Decode', {qrCode});
};
Screen B
The QR code is pulled from the navigation state params and used for an API call (startDecode) through redux.
componentDidMount() {
qrCode = this.props.navigation.state.params.qrCode;
this.props.startDecode(qrCode.data);
}
My issue is that componentDidMount only gets called the first time that route is taken.
Upvotes: 1
Views: 5619
Reputation: 1638
I was facing a similar issue and I used this.props.navigation.addListener()
to resolve it. Basically, force-calling componentDidMount()
may be possible by pushing same screen again using a key (I haven't tried it) but your stack will keep growing as well, which is not optimal. So, when you return to a screen already in stack, you can use addListener()
to see if it is being re-focused, and you can replicate you componentDidMount()
code here:
class MyClass extends Component {
someProcess = () => {
// Code common between componentDidMount() and willFocus()
}
componentDidMount() {
this.someProcess();
}
willFocus = this.props.navigation.addListener(
'willFocus',
(payload) => {
this.someProcess();
}
);
}
When MyClass
is called for the first time, componentDidMount
will get called. For the other times when it is still in stack but instead just gains focus, addListener
will get called.
Upvotes: 2
Reputation: 3297
In react-navigation
each screen is kept mounted. This means that when you you go back to B, you might have changed the props, but componentDidMount
was already invoked in the first creation of this screen.
There are two options available for you (AFAIK) that can handle this case:
this.props.navigation.navigate()
you can use
this.props.navigation.push
which will create another instance of
screen B, thus invoking the componentDidMount
React lifecycle
event.getDerivedPropsFromState
or it can be done in the soon to be
deprecated componentWillReceiveProps
.Upvotes: 2
Reputation: 831
This happens because the B component is mounted only on the first time it is accessed, so componentDidMount won't be called again.
I recommend you to pass a callback to the setOnNavigatorEvent
method of your navigator, with the 'didAppear' event. Your callback will be invoked on every event emitted by react-native-navigation, and you can verify to do your logic every time the screen appears (hence the use of 'didAppear' event). You can base your code on the following:
export default class ExampleScreen extends Component {
constructor(props) {
super(props);
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
}
onNavigatorEvent(event) {
if (event.id === 'didAppear') {
// do API call here
}
}
}
Upvotes: 0