使用 React hook 创建自定义历史记录后退和前进按钮

问题描述 投票:0回答:1

我想使用 React hook 创建自定义历史记录后退和前进按钮。

作为参考,如果有帮助的话,我正在尝试复制 Spotify 网络应用程序中可以看到的行为。他们的自定义前进和后退按钮与浏览器历史记录按钮无缝集成。

我认为我的功能大部分都可以工作,但有一个问题。这是我的 React 钩子:

import { useState, useEffect } from 'react';
import { useHistory } from 'react-router-dom';

const useNavigationHistory = () => {
  const history = useHistory();

  const [length, setLength] = useState(0);
  const [direction, setDirection] = useState(null);
  const [historyStack, setHistoryStack] = useState([]);
  const [futureStack, setFutureStack] = useState([]);

  const canGoBack = historyStack.length > 0;
  const canGoForward = futureStack.length > 0;

  const goBack = () => {
    if (canGoBack) {
      history.goBack();
    }
  };

  const goForward = () => {
    if (canGoForward) {
      history.goForward();
    }
  };

  useEffect(() => {
    return history.listen((location, action) => {
      // if action is PUSH we are going forwards
      if (action === 'PUSH') {
        setDirection('forwards');
        setLength(length + 1);
        // add the new location to the historyStack
        setHistoryStack([...historyStack, location.pathname]);
        // clear the futureStack because it is not possible to go forward from here
        setFutureStack([]);
      }
      // if action is POP we could be going forwards or backwards
      else if (action === 'POP') {
        // determine if we are going forwards or backwards
        if (futureStack.length > 0 && futureStack[futureStack.length - 1] === location.pathname) {
          setDirection('forwards');
          // if we are going forwards, pop the futureStack and push it onto the historyStack
          setHistoryStack([...historyStack, futureStack.pop()]);
          setFutureStack(futureStack);
        } else {
          setDirection('backwards');
          // if we are going backwards, pop the historyStack and push it onto the futureStack
          setFutureStack([...futureStack, historyStack.pop()]);
          setHistoryStack(historyStack);
        }
        setLength(historyStack.length);
      }
    });
  }, [history, length, historyStack, futureStack]);

  return { canGoBack, canGoForward, goBack, goForward };
};

export default useNavigationHistory;

在我的测试中,在各个不同页面之间前后导航时,这一切似乎都工作正常。

问题

如果我通过在相同的两页之间交替向前导航,例如:

/home
/about
/home
/about
/home
/about

...然后我判断我们是前进还是后退的逻辑就崩溃了。

我认为是这一行:

if (futureStack.length > 0 && futureStack[futureStack.length - 1] === location.pathname) {

因为向前路径名和向后路径名是相同的,所以即使我向后走,它也认为我正在向前走。

我一直在试图找出如何解决这个问题,但还没有成功。

有人可以帮忙吗?

也许我的解决方案有缺陷,我需要一种完全不同的方法,我不确定。

reactjs react-hooks react-router-dom browser-history html5-history
1个回答
0
投票

事实证明,react-router-dom 的 useHistory hook 返回的数据已经包含历史记录中每个项目的唯一键值。

因此,解决方案就是简单地将钩子中

location.pathname
的每个实例交换为
location.key
,现在它的行为符合预期。

© www.soinside.com 2019 - 2024. All rights reserved.