使用导航进入新屏幕后如何卸载钩子

时间:2021-06-17 14:03:34

标签: react-native react-navigation-v5

上下文是一个带有 React Navigation 的简单 React Native 应用程序。 有 3 个屏幕。

第一个简单地显示一个按钮,使用 navigation.navigate("SecondScreen") 转到第二个屏幕。

第二个包含一个钩子(见下面的代码),它添加了一个监听器来监听鼠标位置。此挂钩在 useEffect 挂钩中添加侦听器,并在 useEffect 清理函数中移除侦听器。我只是在监听函数里加了一个console.log,看看函数什么时候触发。

此屏幕还包含一个按钮,用于导航到仅显示文本的第三个屏幕。

如果我从第一个屏幕转到第二个屏幕:钩子中的侦听器开始运行。好的。 如果我使用标题中的默认 react navigation 的后退按钮返回到第一个屏幕。听者停止。好的。 如果我再次转到第二个屏幕,则侦听器再次运行。好的。 但是,如果我现在从第二个屏幕转到第三个屏幕,则侦听器仍在运行。不好。

如何在进入第三屏时卸载钩子,并在返回第二屏时重新安装?

请在回答前阅读以下内容:

我知道:

  • 这是因为当我们回到第一个屏幕时,react navigation 会杀死第二个屏幕,然后触发钩子中的 useEffect 返回的清理函数。并且当我们导航到第三个屏幕时它不会杀死第二个屏幕,然后不会触发清理功能。
  • react 导航的钩子 useFocusEffect 可以用来解决这类问题。但是这里不能用,因为会涉及到用useFocusEffect替换hook中的useEffect。而且我希望我的钩子在任何情况下都可以使用,即使没有安装 React 导航。更多,我在这里使用自定义钩子进行解释,但对于任何钩子(例如,本机 useWindowDimensions)都是同样的问题。

那么有谁知道我如何管理这个案例以避免让监听器在第三个屏幕上运行?

这是钩子示例的代码,我取自 https://github.com/rehooks/window-mouse-position/blob/master/index.js,但可以使用任何钩子。

"use strict";
let { useState, useEffect } = require("react");

function useWindowMousePosition() {
  let [WindowMousePosition, setWindowMousePosition] = useState({
    x: null,
    y: null
  });

  function handleMouseMove(e) {
    console.log("handleMouseMove");
    setWindowMousePosition({
      x: e.pageX,
      y: e.pageY
    });
  }

  useEffect(() => {
    window.addEventListener("mousemove", handleMouseMove);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
    };
  }, []);

  return WindowMousePosition;
}

module.exports = useWindowMousePosition;

1 个答案:

答案 0 :(得分:0)

<块引用>

react 导航的钩子 useFocusEffect 可以用来解决这类问题。但是这里不能用,因为会涉及到用useFocusEffect替换hook中的useEffect。而且我希望我的钩子在任何情况下都可以使用,即使没有安装 React 导航

所以你的钩子需要知道导航状态。如果您不能使用 useFocusEffect,则需要传递有关屏幕是否聚焦的信息(例如,使用 enabled 道具)。

function useWindowMousePosition({ enabled = true } = {}) {
  let [WindowMousePosition, setWindowMousePosition] = useState({
    x: null,
    y: null
  });

  useEffect(() => {
    if (!enabled) {
      return;
    }

    function handleMouseMove(e) {
      console.log("handleMouseMove");
      setWindowMousePosition({
        x: e.pageX,
        y: e.pageY
      });
    }

    window.addEventListener("mousemove", handleMouseMove);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
    };
  }, [enabled]);

  return WindowMousePosition;
}

然后根据屏幕焦点传递enabled

const isFocused = useIsFocused();
const windowMousePosition = useWindowMousePosition({ enabled: isFocused });

请注意,与 useFocusEffect 不同,此方法需要在屏幕模糊/聚焦时重新渲染屏幕。

相关问题