返回屏幕时未在 React Native 中调用 useEffect
Posted
技术标签:
【中文标题】返回屏幕时未在 React Native 中调用 useEffect【英文标题】:useEffect not called in React Native when back to screen 【发布时间】:2020-05-27 16:36:52 【问题描述】:你好吗。 这是这个问题的场景。 假设有 2 个屏幕可以使其变得简单。
-
进入A屏。 useEffect of A screen called.
从 A 屏幕导航到 B 屏幕
从 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
钩子只会在第一次渲染时触发,并且只要它的依赖数组中的值更新,所以我怀疑它不会因为没有被重新挂载而再次触发。
【参考方案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)
每次我关闭对话框时都会触发以上是关于返回屏幕时未在 React Native 中调用 useEffect的主要内容,如果未能解决你的问题,请参考以下文章
使用React Native的Firebase查询未在我的屏幕上显示(但在console.log上显示)
react native - 应用程序被杀死/未启动时未收到通知
JavaScript Array flat 函数未在 React native 中定义
Jquery datatable 在从简单的 Web 服务调用 Web 方法时未在表中显示任何数据
为啥当我使用 presentModelViewController 时未在我的 UITabBArController 中调用 viewWillAppear?