我正在使用Material-ui的标签,这些标签受到控制,我将它们用于(React-router)链接,如下所示:
<Tab value={0} label="dashboard" containerElement={<Link to="/dashboard/home"/>}/>
<Tab value={1} label="users" containerElement={<Link to="/dashboard/users"/>} />
<Tab value={2} label="data" containerElement={<Link to="/dashboard/data"/>} />
如果我当前正在访问仪表板/数据,请点击浏览器的后退按钮 我(例如)转到仪表板/用户,但突出显示的Tab仍然停留在仪表板/数据上(值= 2)
我可以通过设置状态进行更改,但是当按下浏览器的后退按钮时,我不知道如何处理该事件?
我发现了这个:
window.onpopstate = this.onBackButtonEvent;
但每次状态更改时都会调用此命令(不仅仅是在后退按钮事件中)
答案 0 :(得分:19)
这是一个有点老问题,你可能已经得到了答案,但对于像我这样需要这个问题的人,我会留下这个答案。
使用react-router使这项工作变得简单:
import { browserHistory } from 'react-router';
componentDidMount() {
super.componentDidMount();
this.onScrollNearBottom(this.scrollToLoad);
this.backListener = browserHistory.listen(location => {
if (location.action === "POP") {
// Do your stuff
}
});
}
componentWillUnmount() {
super.componentWillUnmount();
// Unbind listener
this.backListener();
}
答案 1 :(得分:14)
使用钩子可以检测到后退和前进按钮
import { useHistory } from 'react-router-dom'
const [ locationKeys, setLocationKeys ] = useState([])
const history = useHistory()
useEffect(() => {
return history.listen(location => {
if (history.action === 'PUSH') {
setLocationKeys([ location.key ])
}
if (history.action === 'POP') {
if (locationKeys[1] === location.key) {
setLocationKeys(([ _, ...keys ]) => keys)
// Handle forward event
} else {
setLocationKeys((keys) => [ location.key, ...keys ])
// Handle back event
}
}
})
}, [ locationKeys, ])
答案 2 :(得分:9)
这是我最终如何做到的:
Activity
感谢大家帮助lol
答案 3 :(得分:6)
React Router API的3.x版本a set of utilities可用于公开&#34; Back&#34;事件之前的按钮事件注册浏览器的历史记录。您必须首先将组件包装在withRouter()
higher-order component中。然后,您可以使用setRouteLeaveHook()
函数,该函数接受具有有效route
属性和回调函数的任何path
对象。
import {Component} from 'react';
import {withRouter} from 'react-router';
class Foo extends Component {
componentDidMount() {
this.props.router.setRouteLeaveHook(this.props.route, this.routerWillLeave);
}
routerWillLeave(nextState) { // return false to block navigation, true to allow
if (nextState.action === 'POP') {
// handle "Back" button clicks here
}
}
}
export default withRouter(Foo);
答案 4 :(得分:3)
用于在反应功能组件中向按下浏览器时发出警告。请执行以下步骤
const [isBackButtonClicked, setBackbuttonPress] = useState(false);
window.history.pushState(null, null, window.location.pathname);
window.addEventListener('popstate', onBackButtonEvent);
定义onBackButtonEvent函数并根据需要编写逻辑。
const onBackButtonEvent = (e) => {
e.preventDefault();
if (!isBackButtonClicked) {
if (window.confirm("Do you want to go to Test Listing")) {
setBackbuttonPress(true)
props.history.go(listingpage)
} else {
window.history.pushState(null, null, window.location.pathname);
setBackbuttonPress(false)
}
}
}
在组件中将取消订阅onBackButtonEvent函数
最终代码如下所示
import React,{useEffect,useState} from 'react'
function HandleBrowserBackButton() {
const [isBackButtonClicked, setBackbuttonPress] = useState(false)
useEffect(() => {
window.history.pushState(null, null, window.location.pathname);
window.addEventListener('popstate', onBackButtonEvent);
//logic for showing popup warning on page refresh
window.onbeforeunload = function () {
return "Data will be lost if you leave the page, are you sure?";
};
return () => {
window.removeEventListener('popstate', onBackButtonEvent);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const onBackButtonEvent = (e) => {
e.preventDefault();
if (!isBackButtonClicked) {
if (window.confirm("Do you want to go to Test Listing")) {
setBackbuttonPress(true)
props.history.go(listingpage)
} else {
window.history.pushState(null, null, window.location.pathname);
setBackbuttonPress(false)
}
}
}
return (
<div>
</div>
)
}
export default HandleBrowserBackButton
答案 5 :(得分:1)
我与router hoc一起使用是为了获取历史记录道具,并只编写一个componentDidMount()方法:
componentDidMount() {
if (this.props.history.action === "POP") {
// custom back button implementation
}
}
答案 6 :(得分:1)
挂钩样本
const { history } = useRouter();
useEffect(() => {
return () => {
if (history.action === "POP") // && history.location.pathname === "any specific path") {
history.replace(history.location.pathname, /* the new state */);
}
};
}, [history])
我不使用history.listen,因为它不会影响状态
const disposeListener = history.listen(navData => {
if (navData.pathname === "/props") {
navData.state = /* the new state */;
}
});
答案 7 :(得分:1)
这取决于您在React中使用的路由器的类型。
如上所述,如果您从react-router使用BrowserRouter(尽管在react-router v4中不可用),则可以使用操作“ POP”来拦截浏览器后退按钮。
但是,如果您使用HashRouter推送路由,则上述解决方案将不起作用。原因是当您单击浏览器的后退按钮或从组件中推入路由时,哈希路由器始终以“ POP”操作触发。您无法通过window.popstate或history.listen来区分这两个动作。
答案 8 :(得分:1)
该问题的大多数答案要么使用过时的React Router版本,要么依赖不太现代的Class组件,要么令人困惑;而且都不使用Typescript,这是一种常见的组合。这是使用Router v5,功能组件和Typescript的答案:
// use destructuring to access the history property of the ReactComponentProps type
function MyComponent( { history }: ReactComponentProps) {
// use useEffect to access lifecycle methods, as componentDidMount etc. are not available on function components.
useEffect(() => {
return () => {
if (history.action === "POP") {
// Code here will run when back button fires. Note that it's after the `return` for useEffect's callback; code before the return will fire after the page mounts, code after when it is about to unmount.
}
}
})
}
here中提供了带有说明的完整示例。
答案 9 :(得分:1)
如果你使用的是 React Router V5,你可以试试 Prompt。
<块引用>用于在离开页面之前提示用户。当您的应用程序进入应阻止用户导航离开的状态时(例如表单填写了一半),呈现
<Prompt
message={(location, action) => {
if (action === 'POP') {
console.log("Backing up...")
// Add your back logic here
}
return true;
}}
/>
答案 10 :(得分:1)
只需放入 componentDidMount()
componentDidMount() {
window.onbeforeunload =this.beforeUnloadListener;
}
beforeUnloadListener = (event) => {
event.preventDefault();
return event.returnValue = "Are you sure you want to exit?";
};
答案 11 :(得分:0)
即将发布的6.0版引入了useBlocker钩子-可用于拦截所有导航尝试。
import { Action } from 'history';
import { useBlocker } from 'react-router';
// when blocker should be active
const unsavedChanges = true;
useBlocker((transition) => {
const {
location, // The new location
action, // The action that triggered the change
} = transition;
// intercept back and forward actions:
if (action === Action.Pop) {
alert('intercepted!')
}
}, unsavedChanges);
答案 12 :(得分:0)
使用挂钩。我已经将@Nicolas Keller的代码转换为打字稿
const [locationKeys, setLocationKeys] = useState<(string | undefined)[]>([]);
const history = useHistory();
useEffect(() => {
return history.listen((location) => {
if (history.action === 'PUSH') {
if (location.key) setLocationKeys([location.key]);
}
if (history.action === 'POP') {
if (locationKeys[1] === location.key) {
setLocationKeys(([_, ...keys]) => keys);
// Handle forward event
console.log('forward button');
} else {
setLocationKeys((keys) => [location.key, ...keys]);
// Handle back event
console.log('back button');
removeTask();
}
}
});
}, [locationKeys]);
答案 13 :(得分:0)
您现在可以使用 react-router-dom 中的 useHistory
钩子
import { useHistory } from "react-router-dom";
const history = useHistory();
...
<div onClick={ ()=>history.goBack() }>Back </div>
这将通过点击导航到上一页
答案 14 :(得分:-3)
您可以使用“ withrouter” HOC并使用this.props.history.goBack
。
<Button onClick={this.props.history.goBack}>
BACK
</Button>