反应导航didfocus事件侦听器在类组件和功能组件之间的工作方式不同

chi*_*ote 7 javascript reactjs react-native react-navigation react-hooks

当我切换到此屏幕时,它将执行一些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();
    }
}

Run Code Online (Sandbox Code Playgroud)

控制台输出

从其他导航堆栈到此屏幕的转换:类版本

同一堆栈中屏幕之间的转换:类版本

挂钩版本

const someScreen = ({
 navigation,
}) => {
    useEffect(() => {
        const navFocusListener = navigation.addListener('didFocus', () => {
        // do some API calls here
        API_CALL();
        console.log('hooooks');
    });

    return () => {
        navFocusListener.remove();
    };
  }, []);
}
Run Code Online (Sandbox Code Playgroud)

控制台输出

从其他导航堆栈过渡到此屏幕:控制台中未显示任何内容

同一堆栈中的屏幕之间的过渡:挂钩

顺便说一句,这是我找到的解决方法

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();
          };
      }, []);
}
Run Code Online (Sandbox Code Playgroud)

控制台输出

从其他导航堆栈过渡到此屏幕:重点部分

同一堆栈中屏幕之间的转换:侦听器部分

chi*_*ote 5

我想我找到了不一致行为的根本原因。还有另一个名为 useLayoutEffect 的钩子

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