当我过渡到这个屏幕时,它会做一些API调用来获取最新数据。但是当我从另一个带有钩子版本的导航堆栈转换时,它似乎不会触发 didFocus 事件来触发 api 调用,而它与类版本配合得很好。
如何使钩子版本具有与类版本相同的行为?
这两个版本有什么区别?
类组件版本
class someScreen extends Component {
componentDidMount() {
const {
navigation,
} = this.props;
this.navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
console.log("class version");
API_CALL();
});
}
componentWillUnmount() {
this.navFocusListener.remove();
}
}
控制台输出
从其他导航堆栈过渡到此屏幕:类版本
在同一堆栈中的屏幕之间转换:类版本
钩子版本
const someScreen = ({
navigation,
}) => {
useEffect(() => {
const navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
API_CALL();
console.log('hooooks');
});
return () => {
navFocusListener.remove();
};
}, []);
}
控制台输出
从其他导航堆栈过渡到此屏幕:控制台中不显示任何内容
在同一堆栈中的屏幕之间过渡:呼呜呜
顺便说一句,这是我找到的解决方法
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();
};
}, []);
}
控制台输出
从其他导航堆栈过渡到此屏幕:重点部分
在同一堆栈中的屏幕之间过渡:侦听器部分
我想我找到了不一致行为的根本原因。 还有另一个钩子叫做useLayoutEffect
使用布局效果 签名与 useEffect 相同,但它在所有 DOM 突变后同步触发。使用它从 DOM 读取布局并同步重新渲染。在 useLayoutEffect 中计划的更新将在浏览器有机会绘制之前同步刷新。
useLayoutEffect将阻止绘画,而useEffect不会。 这证实了并解释了我的猜测,即didFocus事件已经触发,但它没有触发侦听器,因为它错过了时间。
所以就我而言,我必须使用 useLayoutEffect 而不是 useEffect
参考: https://kentcdodds.com/blog/useeffect-vs-uselayouteffect https://reactjs.org/docs/hooks-reference.html#uselayouteffect