最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React navigation didfocus event listener works differently between class component and functional component - Stack

programmeradmin0浏览0评论

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

transition from other navigation stack to this screen: focused section

transition between screens in same stack: listener section

Share Improve this question edited Aug 13, 2019 at 3:29 chitsutote asked Aug 12, 2019 at 19:39 chitsutotechitsutote 2212 silver badges6 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

I 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

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论