检测反应路由器中的先前路径?

Posted

技术标签:

【中文标题】检测反应路由器中的先前路径?【英文标题】:Detect previous path in react router? 【发布时间】:2017-01-10 08:44:34 【问题描述】:

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

【问题讨论】:

检查this.props.history.location.pathname。它应该可以工作。 你好,你有什么想法,如何从应用程序或网络应用程序中获取上一页?用户从哪里访问网络应用程序?可以在 reactjs 上检查吗? 【参考方案1】:

您可以在 componentWillReceiveProps 生命周期方法中保存以前的路径。逻辑非常接近troubleshooting section 的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 )
    
  
)

最近,从状态访问它。

【讨论】:

谢谢。我将带有路径的状态与路径名一起推送。你的解决方案更好。 很高兴为您提供帮助! 它对我不起作用。我使用 在我的应用程序中导航,当我单击组件中的任何链接时,componentWillReceiveProps 不会运行。 我使用 componentWillUnmount 设置状态,但如果我移动到其他组件,除非我将其传递给组件,否则我无法访问状态。 @AlexandrLazarev 功能组件呢?你介意更新你的答案吗?提前致谢。【参考方案2】:

如果你使用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;
  

【讨论】:

除此之外,您可以导入动作名称import LOCATION_CHANGE from 'react-router-redux'; 如果你使用connected-react-router你可以使用import LOCATION_CHANGE from 'connected-react-router'; @Stuck 它只是在控制台上打印@@router/LOCATION_CHANGE【参考方案3】:

您可以使用&lt;Link&gt; 组件传递状态,在本例中为路径名:

<Link to=pathname: '/nextpath', state:  prevPath: location.pathname >Example Link</Link>

然后您可以在下一个组件中从this.props.location.state 访问prevPath

【讨论】:

你也可以用browserHistory.push()做同样的事情 巧妙的把戏。但是,如果您不小心,就会有一个明显的问题。页面A 将用户发送到页面B,状态为pathname: pathB, state: prevPath: pathA。当在页面B 并且用户导航到上一个页面,传递类似结构的状态时,您可以看到问题。 这会重定向到运行在 3000 端口的 API 主机,react app 在 3001 上。如何解决? 使用state 对我来说是有问题的,因为它在刷新后仍然存在。填写表格后,我在“谢谢”页面上使用它。如果他们不是来自原始表单,我不希望人们访问此页面。还是我做错了? 是的,状态是一个非常糟糕的答案【参考方案4】:

如果您使用的是&lt;Redirect /&gt; 组件,您可以添加一个from 属性,该属性将添加到您重定向到的组件中的location.state

// in the redirecting component
<Redirect
to=
  pathname: '/login',
  state:  from: location 

/>

//in the other component you redirected to
...
const  location  = props.location.state;
...

【讨论】:

您能否添加有关“其他组件”的更多详细信息?以及如何传递和访问道具?谢谢【参考方案5】:

使用 react-routeruseHistory 钩子可以在功能组件的无状态中转到上一个路径。更多信息请点击链接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>
    ):

【讨论】:

您应该注意,如果您重新加载页面,那么新的先前路径将成为您刚刚重新加载的路径。如果你重新加载2次然后尝试history.goBack(),你会遇到两次相同的页面,这不是你通常想要的。 现在是 2021 年,情况并非如此。我相信他们已经更新了它并且他们已经修复了这个错误 @Dev。我在我的代码中使用了上面的代码,并多次尝试重新加载页面,但效果很好。 这种方法的问题是它保留了 > 浏览器按钮并且 > 变为启用状态。如果您想始终在最新页面上(> 禁用),而只是将上一个屏幕显示为您的最新页面,这是行不通的。 这提供了一种向后导航的方法。但它没有提供访问问题所在的前一个 URL 的方法【参考方案6】:

如果有帮助,如果您不希望组件重新渲染并仍然获得以前的路径,请参阅此解决方案..

import  useLocation  from 'react-router-dom';


export default () => 
  const location = useLocation();
  const path = location.pathname;
  const store = window.localStorage;
  let url = '';
  let prevUrl = '';

  url = store.getItem('url');
  store.setItem('prevUrl', url);
  store.setItem('url', path);

  url = store.getItem('url');
  prevUrl = store.getItem('prevUrl');

  return  url, prevUrl ;


【讨论】:

只需将其导入您想要的位置并执行const url, prevUrl = importedFunc(); 在 s-s-r 中小心:窗口对象未定义。【参考方案7】:

React - 使用 props 获取上一个路径

console.log(props.history.location.state && props.history.location.state.from.pathname);

如果你使用&lt;Link&gt; OR &lt;Redirect&gt; ? pathname : undefined重定向

【讨论】:

【参考方案8】:

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

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

history.push(`/device/detail`,  from: 'device detail page'  );

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

【讨论】:

谢谢!出于某种原因,我不知道在哪里可以找到from,但多亏了你,我找到了它。 const history = useHistory(); console.log(history.location.state.from); 只是history.location.from 而不是history.location.state.from @Quirzo 应该是 history.location.state.from 因为 history.location 没有 from 属性。所以 history.location.from 不应该存在。你可以确认这个@defraggled 您能否粘贴更详细的答案,以便人们从您的出色答案中受益?现在它没有处于有用的状态,因为没有例子说明事情是如何联系在一起的......任何愿意改进这个答案的人??? 您的回答值得 100 票赞成,谢谢:D【参考方案9】:

使用context可以存储之前的location路径名:

const RouterContext = React.createContext();

const RouterProvider = (children) => 
  const location = useLocation()
  const [route, setRoute] = useState( //--> It can be replaced with useRef or localStorage
    to: location.pathname,
    from: location.pathname //--> previous pathname
  );

  useEffect(()=> 
    setRoute((prev)=> (to: location.pathname, from: prev.to) )
  , [location]);
  
  return <RouterContext.Provider value=route>
    children
  </RouterContext.Provider>

然后在RouterProvider下的某个组件中:

const route = useContext(RouterContext);
//...
<Link to=route.from>
  Go Back
</Link>

或者

history.push(route.from);

注意RouterContext 应该在Router 组件下,如果您不想更新状态,可以改用useRef。如果您需要更多持久性,请使用localStorage

【讨论】:

【参考方案10】:

此答案使用与@AlexandrLazarev 类似的方法,但通过 React Hooks 实现。这可确保捕获对路径的所有更改,无论它们是如何启动的。先前的路径值存储在***组件的状态中,然后可以作为道具传递给子组件,或者如果您使用像 Redux 这样的全局状态提供程序,可以将其添加到存储中:

import  useEffect, useState  from 'react'

cont App = ( location ) => 
  const [currentPath, setCurrentPath] = useState(null);
  const [previousPath, setPreviousPath] = useState(null);

  useEffect(() => 
    if (location.pathname !== currentPath) 
      setPreviousPath(currentPath);
      setCurrentPath(location.pathname);
    
  , [location.pathname]);

标记中的实现类似于下面的 sn-p。我一直在使用 Reach Router,但考虑到它的 been merged 和 React Router 应该也可以在那里工作。 Router component 使 location 属性可供其所有子级使用,并在其 pathname 属性下保存当前路径的值

<Router>
  <App path="/*" />
<Router/>

【讨论】:

【参考方案11】:

我需要一种方法来有条件地导航,仅当先前的路径等于特定路径时。有了一个功能组件,它的工作原理是这样的。仅当路由为 '/cart' 时,&amp;&amp; 才会触发 .push() 方法。

import useHistory from "react-router-dom";

const history = useHistory();

history.location.pathname === '/cart' && history.push('/checkout');

【讨论】:

"仅当先前路径等于特定路径时才导航" 但是这个 - history.location.pathname 是当前路径。

以上是关于检测反应路由器中的先前路径?的主要内容,如果未能解决你的问题,请参考以下文章

根据路由反应路由器导航栏

为啥反应路由器不工作。当我改变路径?

text 过渡运动反应路由器4路径转换

activeClassName 不适用于可变路径的反应路由器

反应路由器:无法读取未定义的属性“路径名”

我对反应路由器的相对路径有困难。基本路径从位置栏中消失