When I transition to this screen, it will do some API calls to fetch the latest data. But it seems not trigger the didFocus event to fire the api calls when I transition from another navigation stack with hooks version while it works well with class version.
How do I make hooks version have the same behavior as class version?
What's the difference between this two version?
class ponent version
class someScreen extends Component {
ponentDidMount() {
const {
navigation,
} = this.props;
this.navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
console.log("class version");
API_CALL();
});
}
ponentWillUnmount() {
this.navFocusListener.remove();
}
}
console output
transition from other navigation stack to this screen: class version
transition between screens in same stack: class version
Hooks version
const someScreen = ({
navigation,
}) => {
useEffect(() => {
const navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
API_CALL();
console.log('hooooks');
});
return () => {
navFocusListener.remove();
};
}, []);
}
console output
transition from other navigation stack to this screen: nothing is shown in console
transition between screens in same stack: hooooks
BTW, here is the workaround solution I found
const someScreen = ({
navigation,
}) => {
useEffect(() => {
const isFocused = navigation.isFocused();
// manually judge if the screen is focused
// if did, fire api call
if (isFocused) {
// do the same API calls here
API_CALL();
console.log('focused section');
}
const navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
API_CALL();
console.log('listener section');
});
return () => {
navFocusListener.remove();
};
}, []);
}
console output
transition from other navigation stack to this screen: focused section
transition between screens in same stack: listener section
When I transition to this screen, it will do some API calls to fetch the latest data. But it seems not trigger the didFocus event to fire the api calls when I transition from another navigation stack with hooks version while it works well with class version.
How do I make hooks version have the same behavior as class version?
What's the difference between this two version?
class ponent version
class someScreen extends Component {
ponentDidMount() {
const {
navigation,
} = this.props;
this.navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
console.log("class version");
API_CALL();
});
}
ponentWillUnmount() {
this.navFocusListener.remove();
}
}
console output
transition from other navigation stack to this screen: class version
transition between screens in same stack: class version
Hooks version
const someScreen = ({
navigation,
}) => {
useEffect(() => {
const navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
API_CALL();
console.log('hooooks');
});
return () => {
navFocusListener.remove();
};
}, []);
}
console output
transition from other navigation stack to this screen: nothing is shown in console
transition between screens in same stack: hooooks
BTW, here is the workaround solution I found
const someScreen = ({
navigation,
}) => {
useEffect(() => {
const isFocused = navigation.isFocused();
// manually judge if the screen is focused
// if did, fire api call
if (isFocused) {
// do the same API calls here
API_CALL();
console.log('focused section');
}
const navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
API_CALL();
console.log('listener section');
});
return () => {
navFocusListener.remove();
};
}, []);
}
console output
Share Improve this question edited Aug 13, 2019 at 3:29 chitsutote asked Aug 12, 2019 at 19:39 chitsutotechitsutote 2212 silver badges6 bronze badgestransition from other navigation stack to this screen: focused section
transition between screens in same stack: listener section
1 Answer
Reset to default 5I guess I found the root cause of the inconsistent behavior. There is another hook called useLayoutEffect
useLayoutEffect The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.
the useLayoutEffect will block the painting while the useEffect will not. That confirm and explains my guess that the didFocus event had fired, but it didn't trigger the listener since it miss the timing
so in my case, I have to use useLayoutEffect instead of useEffect
reference: https://kentcdodds./blog/useeffect-vs-uselayouteffect https://reactjs/docs/hooks-reference.html#uselayouteffect