检测路由器中的上一个路径?

vij*_*yst 24 reactjs react-router

我正在使用反应路由器.我想从我来自的地方检测上一页(在同一个应用程序中).我在我的上下文中有路由器.但是,我没有在路由器对象上看到任何属性,如"上一个路径"或历史记录.我该怎么做?

Sam*_*gan 30

您可以使用<Link>组件传递状态,在本例中为路径名:

<Link to={{pathname: '/nextpath', state: { prevPath: location.pathname }}}>Example Link</Link>
Run Code Online (Sandbox Code Playgroud)

然后,您可以prevPaththis.props.location.state下一个组件中进行访问

  • 您也可以使用“ browserHistory.push()”进行相同的操作 (2认同)
  • 巧妙的技巧。然而,如果你不小心的话,就会出现一个明显的问题。页面“A”将用户发送到页面“B”,状态为“{pathname: pathB, state: { prevPath: pathA}}”。当在页面“B”上并且用户导航到上一页时,传递类似结构的状态,您可以看到问题。 (2认同)

Bry*_*Lee 25

不要检查上一页是什么,而是从不同的角度解决问题。将当前页面作为道具传递给您要导航到的组件或链接。

在我调用 history.push 或单击链接的上一个页面或组件中,我添加了我所在的当前页面的状态,例如

history.push(`/device/detail`, { from: 'device detail page' } );
Run Code Online (Sandbox Code Playgroud)

然后我可以使用 history.location.state.from 访问上一页的内容

  • 谢谢!由于某种原因,我不明白在哪里可以找到“来自”,但多亏了你,我找到了它。`const 历史 = useHistory(); console.log(history.location.state.from);` (5认同)
  • 这可行,但不适用于浏览器导航。如果用户单击后退按钮,我们可能无法准确确定他来自哪个页面或状态。 (4认同)

Dan*_*son 24

如果您正在使用react-router-redux,则可以创建一个reducer,它可以挂接react-router-redux调度的事件.

export default function routerLocations(state = [], action) {
  switch (action.type) {
    case "@@router/LOCATION_CHANGE":
      return [...state, action.payload]
    default:
      return state;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 除此之外,您可以从'react-router-redux'导入操作名称`import {LOCATION_CHANGE};` (7认同)
  • 如果您使用的是 `connected-react-router` 您可以使用 `import { LOCATION_CHANGE } from 'connected-react-router';` (2认同)

Ale*_*rev 15

您可以在componentWillReceiveProps生命周期方法中保存以前的路径.该逻辑非常接近于docs的故障排除部分中提供的示例react-router.

<Route component={App}>
  {/* ... other routes */}
</Route>

const App = React.createClass({
  getInitialState() {
    return { prevPath: '' }
  },

  componentWillReceiveProps(nextProps) {
    if (nextProps.location !== this.props.location) {
      this.setState({ prevPath: this.props.location })
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

最近,从州访问它.

  • @AlexandrLazarev 功能组件怎么样?您介意更新您的答案吗?提前致谢。 (3认同)

sha*_*rma 11

使用react-router 的useHistory钩子,在功能组件的无状态状态下跳转到之前的路径。有关更多信息,请点击链接https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/hooks.md#useroutematch

import { useHistory } from "react-router-dom";

function demo () {
    let history = useHistory();
    const goToPreviousPath = () => {
        history.goBack()
    }
    return (
      <div>
        <Button
          onClick={goToPreviousPath}
        >
          Back
        </Button>
      </div>
    ):
}
Run Code Online (Sandbox Code Playgroud)

  • 但是,您应该注意,如果重新加载页面,新的先前路径将成为您刚刚重新加载的路径。如果您重新加载两次,然后尝试“history.goBack()”,您将遇到相同的页面两次,这不是您通常想要的。 (8认同)
  • 这提供了一种向后导航的方法。但它没有提供访问前面的 URL 的方法,这正是问题所要求的 (7认同)
  • 现在情况并非如此,现在是 2021 年了。我相信他们已经更新了它,并且已经修复了该错误 @Dev。我在我的代码中使用了上面的代码,并尝试多次重新加载页面,但它工作得很好。 (2认同)
  • 这种方法的问题是它保留了 &lt;/&gt; 浏览器按钮并且 &gt; 被启用。如果您想始终位于最新页面(&gt;禁用),但只是将上一屏幕显示为最新页面,则这是行不通的。 (2认同)

wol*_*fvc 8

从 08/2022 开始,对于使用 React Router v6 的用户,您可以使用 Navigate 组件、Link 组件或 useNavigate 钩子将前一个 url 传递到下一个组件:

在重定向组件中:

// with Navigate component (same as with Link component):
const location = useLocation();
...
<Navigate to="/nextpath" state={ { from: location } } />
...


// with useNavigate hook:
const navigate = useNavigate();
const location = useLocation();
....
navigate("/nextpath", { state: { from: location } });
...
Run Code Online (Sandbox Code Playgroud)

在您重定向到的组件中:

...
const location = useLocation();
let from = location.state?.from?.pathname;
...
Run Code Online (Sandbox Code Playgroud)


Mar*_*ton 6

您可以使用 来监听并构建一个返回堆栈history.listen。这是一个可以做到这一点的钩子。

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

const useBrowserBackStack = () => {
  const history = useHistory();
  const [backStack, setBackStack] = useState<Location[]>([]);
  useEffect(() => {
    history.listen((location, action) => {
      setBackStack(backStack => {
        switch (action) {
          case 'POP':
            return backStack.slice(0, backStack.length - 1);
          case 'PUSH':
            return [...backStack, location];
          case 'REPLACE':
            return [...backStack.slice(0, backStack.length - 1), location];
        }
      });
    });
  }, [setBackStack, history]);
  return backStack;
};

export default useBrowserBackStack;
Run Code Online (Sandbox Code Playgroud)

然后像这样在你的顶级组件中使用

const backStack = useBrowserBackStack();
Run Code Online (Sandbox Code Playgroud)