【问题标题】:useEffect not called in React Native when back to screen返回屏幕时未在 React Native 中调用 useEffect
【发布时间】:2020-05-27 16:36:52
【问题描述】:

你好吗。 这是这个问题的场景。 假设有 2 个屏幕可以使其变得简单。

  1. 进入A屏。 useEffect of A screen called.
  2. 从 A 屏幕导航到 B 屏幕
  3. 从 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])
    }
    

所以再次回到A屏时A屏的更新状态保持不变(不是从道具加载)

我没有更改屏幕 B 中的 props.user。 但我认为const [roleID, setRoleID] = useState(props.user.SELECTED_ROLE.id)至少应该调用这一行。

我正在使用 redux-persist。我认为这不是问题。 对于导航,我使用这个

// 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()
    );
}

屏幕出现时我可以使用任何回调吗? 我的代码有什么问题?

谢谢

【问题讨论】:

  • 当你回到屏幕 A 时是否更改了 props.user?
  • useEffect 不再被调用,因为 props.user 在您的情况下保持不变...您可以在一个组件中使用多个 useEffects :)
  • 您如何在屏幕之间导航?可以加点代码吗?
  • 你用的是什么导航包?导航做更多的堆栈而不是卸载“后退”“页面”吗? useEffect 钩子只会在第一次渲染时触发,并且只要它的依赖数组中的值更新,所以我怀疑它不会因为没有被重新挂载而再次触发。

标签: reactjs react-native use-effect


【解决方案1】:

当您从 A 导航到 B 时,组件 A 不会被销毁(它保留在导航堆栈中)。因此,当您返回时,代码不会再次运行。

也许是一种更好的方式来实现您想要使用导航生命周期事件(我假设您使用的是react-navigation)即订阅didFocus 事件并在组件聚焦时运行您想要的任何代码例如

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

不要忘记在适当的时候取消订阅,例如

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

【讨论】:

  • 我可以知道如何取消订阅吗?
  • 要取消订阅,你只需要调用从addListener返回的函数。在上面的例子中,我称之为unsubscribe。我也更新了上面的答案。希望这是有道理的。
  • 如果你使用 react-navigation 5.x 试试useFocusEffect
【解决方案2】:

以下解决方案对我有用:

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 (
        ......
        ......
    )
}

我用过 react navigation 5+

@react-navigation/native": "5.6.1"

【讨论】:

  • 我用过useEffect(() => { if(isFocused){ console.log("called"); getInitialData(); } }, [ isFocused]); 似乎效果更好
  • 完美,非常智能的解决方案
【解决方案3】:

当前版本的 React Navigation 提供了 useFocusEffect 钩子。见here

【讨论】:

    【解决方案4】:

    React Navigation 5 提供了一个 useFocusEffect 钩子,类似于 useEffect,唯一的区别是它只在屏幕当前聚焦时运行。查看文档https://reactnavigation.org/docs/use-focus-effect

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

    【讨论】:

    • sigh...每次我关闭屏幕上的对话框时,应用程序都会将此行为视为将屏幕聚焦在对话框下方。所以我的useFocusEffect() 中的setShowDialog(true) 每次我关闭对话框时都会触发
    猜你喜欢
    • 2021-09-05
    • 1970-01-01
    • 2018-03-18
    • 2021-05-16
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    相关资源
    最近更新 更多