我有这些场景
设置页面 -> 结果页面 -> 详细信息页面
用户选择设置,单击“下一步”,获取结果,然后单击查看更多详细信息。
详情页面 -> 结果页面
用户从详细信息页面返回结果页面。这会导致完全重新渲染,导致我毫无意义地再次访问服务器(我将结果存储在数组中)。
详细信息页面 -> 结果页面 -> 设置页面 -> 结果页面
用户转到详细信息,然后返回结果(想要抓取存储的结果),然后返回设置页面,进行更改,然后返回结果页面(现在我想再次从服务器完全抓取)。
我想知道反应路由器是否有办法确定我是否通过浏览器历史记录来到该页面,或者我是否正在向前移动。
我一直在寻找同样的东西,然后我终于找到了一个看似简单的解决方案。
快速回答:
我使用
history.action
值来确定用户是来自后退按钮还是来自经典导航。
如果 history.action
等于 'POP'
,则已按下后退按钮。否则就是'PUSH'
。
详细解答:
我可以访问每个页面的道具中的历史记录,因为我做了类似的事情:
<Provider store = { store }>
<AppRouter />
</Provider>
哪里
AppRouter
是:
import React from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import createHistory from 'history/createBrowserHistory';
import PublicRoute from './PublicRoute';
import PageHome from '../pages/front/home/PageHome';
export const history = createHistory();
const AppRouter = () => (
<Router history={ history }>
<div>
<Switch>
<PublicRoute
exact = { true }
path = "/"
component = { PageHome }
history={ history }
/>
< ..... Other routes here ..... >
</Switch>
</div>
</Router>
);
export default AppRouter;
和
PublicRoute
组件是这样的:
import React from 'react';
import { Route } from 'react-router-dom';
import Header from '../components/header/Header';
const PublicRoute = ( { component: Component, ...rest } ) => (
<Route
component={ ( props ) => (
<div>
<Header />
<Component { ...props } />
</div>
)}
{ ...rest }
/>
);
export default PublicRoute;
在 React Router 中,如果路由器调用该组件的子级路径,则该组件将保持挂载状态。因此,在您的示例中,您可以执行以下操作:
<Route path="items" component={Results}>
<Route path=":id" component={Detail} />
</Route>
这样,当安装
Results
组件时,Detail
组件就不会被卸载,因为 Detail
是 Results
的子组件。但是,如果您不希望在详细信息中看到结果组件被渲染,则只能在子组件存在时渲染它们。类似于以下内容:
class Results extends React.Component {
render() {
if (this.props.children) {
// This will enter Detail component
return this.props.children;
}
return (
// Render results component
);
}
}
以上所有答案大多都是旧的。 您可以使用react-router-dom中的useBlocker(),这将帮助您在导航到其他页面时检测场景。
使用示例代码:
import {
useBlocker
} from "react-router-dom";
let blocker = useBlocker(
({
currentLocation,
nextLocation
}) =>
currentLocation.pathname !== nextLocation.pathname && unsavedChanges
);
useEffect(() => {
if (blocker.state === "blocked") {
setOpenSaveContentModal(true);
}
}, [blocker]);