React 导航事件侦听器被多次调用

bar*_*rte 6 reactjs react-navigation

我正在尝试使用功能组件方法在反应导航上实现一些侦听器:

const ExampleComponent = () => {

  const [subs, setSubs] = React.useState([]); 
  React.useEffect(() => {
    setSubs([
      navigation.addListener('willFocus', () => console.log('will focus')),
      navigation.addListener('willBlur', () => console.log('will blur')),
      navigation.addListener('didFocus', () => console.log('did focus')),
      navigation.addListener('didBlur', () => console.log('did blur')),
    ]);

    return () => {
      setSubs([]) 
    }
  }, [])

  return (
    ...
  )
};
Run Code Online (Sandbox Code Playgroud)

遵循建议:https : //fantashit.com/navigation-listeners-firing-multiple-times-per-event/

然而,似乎正在发生的事情是每个听众都被调用了两次,我不确定如何解决这个问题?

小智 9

对于 React Native 来说,无论何时为任何已安装的屏幕添加侦听器,侦听器在屏幕卸载后仍然处于活动状态。每当此类侦听器尝试更改已卸载屏幕的状态时,React Native 都会生成警告。
因此,每当您安装屏幕时,请始终尝试添加侦听器,并在卸载时删除相同的侦听器

const ExampleComponent = () => {

  const [subs, setSubs] = React.useState([]); 
  React.useEffect(() => {
    setSubs([
      navigation.addListener('willFocus', () => console.log('will focus')),
      navigation.addListener('willBlur', () => console.log('will blur')),
      navigation.addListener('didFocus', () => console.log('did focus')),
      navigation.addListener('didBlur', () => console.log('did blur')),
    ]);

    const unsubscribe = () =>{
    navigation.removeAllListeners();
    }
    // Remove all listeners, because there have to be no listeners on unmounted screen
    return () => unsubscribe();
  }, [])
Run Code Online (Sandbox Code Playgroud)

同样可以通过反应导航中的以下内容来实现


useFocusEffect(
    React.useCallback(() =>{

      // Listening on the refresh event
       RefreshEventEmitter.addListener("refresh", () => {
         console.log("Refresh event emitted");
       });

      // ----------------------------------------------
      // Removing all the listeners, so that screen does not re-render after unmounting..
      const unsubscribe = () => {
        RefreshEventEmitter.removeAllListeners();
      };

 
      // Returned function is called when screen is unmounted from display!!
      return () => unsubscribe();
    }, [])
  );
Run Code Online (Sandbox Code Playgroud)

当屏幕安装到显示器上时,useFocusEffect 被调用一次,并且当屏幕从显示器上卸载时,调用 useFocusEffect 的返回函数。


Aje*_*hah 7

正如文档所说:

addListener 返回一个函数,可以调用该函数来取消订阅事件。

尝试在清理函数中清理每个订阅:

React.useEffect(() => {
  const unSubs = [
    navigation.addListener('willFocus', () => console.log('will focus')),
    navigation.addListener('willBlur', () => console.log('will blur')),
    navigation.addListener('didFocus', () => console.log('did focus')),
    navigation.addListener('didBlur', () => console.log('did blur')),
  ]

  return function cleanup() {
    unSubs.forEach((unSub) => {
      unSub()
    })
  }
}, [])
Run Code Online (Sandbox Code Playgroud)