gpt4 book ai didi

javascript - React Native BackHandler 不跟随状态更新

转载 作者:行者123 更新时间:2023-12-05 08:29:47 27 4
gpt4 key购买 nike

我在 BackHandler 事件监听器中使用的 backAction 函数使用 stage 状态作为条件,但不遵循状态值更新当 stage 被其他组件更新时,因为它停留在初始状态值上。并返回 true 和 false 不做任何事情。

预期行为:

如果按下后退按钮检查当前阶段:

  • 如果阶段值为 1,则使用 return false 触发后退按钮默认行为并导航回上一屏幕(无需使用 navigation.goBack()).
  • 如果阶段值大于 1 则只减少当前阶段值减 -1,返回 true 以停止事件冒泡。

当前行为:

一旦按下后退按钮:

  • 在每次点击 stage 时使用并继续使用初始值 1,即使很明显其他组件更改了它并使用了它的新值。
  • return false 甚至不会触发后退按钮的默认行为。

重现代码:

const [stage, setStage] = useState(1);

const backAction = async () => {
console.log(stage); // the bug: stage is always 1

if (stage === 1) {
console.log("Going back to previous screen!");
return false;
} else if (stage > 1) {
console.log("Setting stage back with -1");
await setStage((prevState) => prevState - 1);
return true;
}

return false;
};

useEffect(() => {
BackHandler.addEventListener("hardwareBackPress", backAction);

return () => BackHandler.removeEventListener("hardwareBackPress", backAction);
}, []);

注意:我使用了将 BackHandler.addEventListener 分配给 backHandler 的文档模式,然后在事件清理中使用它作为 backHandler.remove()。也不起作用,但为了简单起见,将其删除。

如有任何帮助,我们将不胜感激。

最佳答案

首先:事件处理程序的返回值被传递给 JS 运行时的事件监听器系统。它不接受 promise ,它不知道如何接受 promise 。但是 promise 是一个真值,这意味着您的处理程序有效地返回 true 只是因为您将其标记为 async

其次,setState 不是异步的(即未声明为 async),这意味着无需await。代码仍会运行,但没有任何好处。而且,由于这是处理程序中唯一使用 async 的方法,删除它可以让您将处理程序转换为同步代码,这是正确响应 hardwareBackPress 的必要条件.

第三,返回 false 与您希望 native 行为发生时应该做的相反。您必须返回 true 才能获得默认行为,否则返回 false

以上段落是错误的。每this documentation ,您对返回值的想法是正确的。 (抱歉;我的 native react 技能生锈了。我已经更正了下面的代码示例以反射(reflect)这一点。)

第三(对于 realz):只要 stage 的值发生变化,您就需要告诉 React Hooks 重新绑定(bind)事件处理程序。需要这样做的原因是闭包将保留函数定义时 stage 的值,并且它不会接收更新。您可以通过在 Hook 的依赖项中列出该变量来执行此操作。这就是您在运行时看到陈旧值的原因。

尝试这样的事情:

const [stage, setStage] = useState(1);

const backAction = () => {
console.log(stage);

if (stage === 1) {
console.log("Going back to previous screen!");
return false;
} else if (stage > 1) {
console.log("Setting stage back with -1");
setStage((prevState) => prevState - 1);
return true;
}

return false;
};

useEffect(() => {
BackHandler.addEventListener("hardwareBackPress", backAction);

return () => BackHandler.removeEventListener("hardwareBackPress", backAction);
}, [ stage ]); // <-- this is the part you're missing

关于javascript - React Native BackHandler 不跟随状态更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68262955/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com