简体   繁体   English

返回屏幕时在 React Native 中不调用 useEffect

[英]useEffect not called in React Native when back to screen

How are you.你好吗。 This is scenario of this issue.这是这个问题的场景。 Let's say there are 2 screens to make it simple.假设有 2 个屏幕以简化操作。

  1. enter A screen.进入A画面。 useEffect of A screen called.使用调用屏幕的效果。
  2. navigate to B screen from A screen从 A 屏幕导航到 B 屏幕
  3. navigate back to A screen from B. at this time, useEffect is not called.从 B 导航回 A 屏幕。此时,没有调用 useEffect。

     function CompanyComponent(props) { const [roleID, setRoleID] = useState(props.user.SELECTED_ROLE.id) useEffect(()=>{ // this called only once when A screen(this component) loaded, // but when comeback to this screen, it doesn't called setRoleID(props.user.SELECTED_ROLE.id) }, [props.user]) }

So the updated state of Screen A remain same when comeback to A screen again (Not loading from props)因此,当再次回到 A 屏幕时,屏幕 A 的更新 state 保持不变(不是从道具加载)

I am not changing props.user in screen B. But I think const [roleID, setRoleID] = useState(props.user.SELECTED_ROLE.id) this line should be called at least.我没有在屏幕 B 中更改 props.user。但我认为至少应该调用const [roleID, setRoleID] = useState(props.user.SELECTED_ROLE.id)这一行。

I am using redux-persist.我正在使用 redux-persist。 I think this is not a problem.我认为这不是问题。 For navigation, I use this对于导航,我使用这个

// to go first screen A, screen B
function navigate(routeName, params) {
    _navigator.dispatch(
        NavigationActions.navigate({
            routeName,
            params,
        })
    );
}
// when come back to screen A from B
function goBack() {
    _navigator.dispatch(
        NavigationActions.back()
    );
}

Is there any callback I can use when the screen appears?当屏幕出现时,我可以使用任何回调吗? What is wrong with my code?我的代码有什么问题?

Thanks谢谢

Below solution worked for me:以下解决方案对我有用:

import React, { useEffect } from "react";
import { useIsFocused } from "@react-navigation/native";

const ExampleScreen = (props) => {
    const isFocused = useIsFocused();

    useEffect(() => {
        console.log("called");
 
        // Call only when screen open or when back on screen 
        if(isFocused){ 
            getInitialData();
        }
    }, [props, isFocused]);

    const getInitialData = async () => {}    

    return (
        ......
        ......
    )
}

I've used react navigation 5+我用过反应导航 5+

@react-navigation/native": "5.6.1" @react-navigation/native": "5.6.1"

When you navigate from A to B, component A is not destroyed (it stays in the navigation stack).当您从 A 导航到 B 时,组件 A 不会被销毁(它保留在导航堆栈中)。 Therefore, when you navigate back the code does not run again.因此,当您向后导航时,代码不会再次运行。

Perhaps a better way to acheive what you want to to use the navigation lifecycle events (I am assuming you are using react-navigation ) Ie subscribe to the didFocus event and run whatever code you want whenever the component is focussed Eg也许是一种更好的方式来实现您想要使用导航生命周期事件(我假设您正在使用react-navigation )即订阅didFocus事件并在组件集中时运行您想要的任何代码例如

const unsubscribe = props.navigation.addListener('didFocus', () => {
    console.log('focussed');
});

Don't forget to unsubscribe when appropriate eg不要忘记在适当的时候取消订阅,例如

// sometime later perhaps when the component is unmounted call the function returned from addListener. In this case it was called unsubscribe
unsubscribe();

The current version of React Navigation provides the useFocusEffect hook.当前版本的 React Navigation 提供了 useFocusEffect 钩子。 See here .这里

React Navigation 5 provide a useFocusEffect hook, is analogous to useEffect, the only difference is that it only runs if the screen is currently focused. React Navigation 5 提供了一个 useFocusEffect 钩子,类似于 useEffect,唯一的区别是它仅在屏幕当前聚焦时运行。 Check the documentation https://reactnavigation.org/docs/use-focus-effect检查文档https://reactnavigation.org/docs/use-focus-effect

 useFocusEffect( useCallback(() => { const unsubscribe = setRoleID(props.user.SELECTED_ROLE.id) return () => unsubscribe() }, [props.user]) )

Solution with useEffect使用useEffect的解决方案

import { useNavigation } from '@react-navigation/native';

const Component = (props) => {
  const navigation = useNavigation()
  const isFocused = useMemo(() => navigation.isFocused(), [])
  useEffect(() => {
    if (isFocused) {
      // place your logic
    }
  }, [isFocused])
}

The above mentioned solution would work definitely but in any case you need to know why it happens is,上面提到的解决方案肯定会起作用,但无论如何你需要知道它为什么会发生,

In react native all the screens are stacked meaning they follow the LAST-IN-FIRST-OUT order, so when you are on a SCREEN A and go.Back(), the component(Screen A) would get un-mounted because it was the last screen that was added in the stack but when we naviagte to SCREEN B, it won't get un-mounted and the next SCREEN B would be added in the stack.在 react native 中,所有屏幕都是堆叠的,这意味着它们遵循LAST-IN-FIRST-OUT顺序,因此当您在 SCREEN A 上并 go.Back() 时,组件(Screen A)将被卸载,因为它是堆栈中添加的最后一个屏幕,但是当我们导航到屏幕 B 时,它不会被卸载,并且下一个屏幕 B 将被添加到堆栈中。

So now, when you go.Back() to SCREEN A, the useEffect will not run because it never got un-mounted.所以现在,当你 go.Back() 到 SCREEN A 时,useEffect 将不会运行,因为它从未被卸载。 React-native keeps the navigation this way to make it look more responsive and real time . React-native 以这种方式保持导航,使其看起来更具响应性和实时性。

if you want to un-mount the Screen everytime you navigate to some other screen you might want to try navigation.replace than navigation.navigate如果您想在每次导航到其他屏幕时卸载屏幕,您可能想尝试使用navigation.replace而不是 navigation.navigate

Hope this helps you.希望这对您有所帮助。

import { useIsFocused } from "@react-navigation/native"; 
 
const focus = useIsFocused();  // use if focus as shown          
 
useEffect(() => {  // whenever you are in the current screen, it will be true vice versa
   handleGetProfile();
}, [focus]);

more更多的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM