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

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

【问题讨论】:

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

标签: reactjs react-router


【解决方案1】:

您可以在 componentWillReceiveProps 生命周期方法中保存以前的路径。逻辑非常接近troubleshooting sectionreact-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(); 在 SSR 中小心:窗口对象未定义。
【解决方案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 是当前路径。
        猜你喜欢
        • 2020-09-08
        • 2022-01-17
        • 1970-01-01
        • 2019-08-03
        • 1970-01-01
        • 1970-01-01
        • 2016-06-05
        • 1970-01-01
        相关资源
        最近更新 更多