我在React的SPA中工作,不使用React Router来创建任何Routes;我不需要让用户导航到特定的页面。想象一下多页的问卷,按顺序填写)。
但是,当用户按下返回按钮时 在浏览器上我不希望他们退出整个应用程序;我希望能够在用户按下后退按钮时启动一个功能,简单地将页面渲染成他们最后选择之前的样子。(每个页面都是一个组件,它们被组装在一个数组中,由一个叫做 currentPage
状态变量(来自状态钩子),所以我可以简单地呈现出这个 pages[currentPage -1]
.
使用(如果需要的话)当前版本的React Router(v5)、函数组件和Typescript,我怎样才能访问back-button事件,既禁用它,又用我自己的函数替换它?
我找到的其他答案要么使用类组件,要么使用React Router旧版本特有的函数,要么使用特定的框架,比如Next.js)。
任何和所有的见解都是感激的。
经过太多时间的努力,我找到了一个解决方案。由于最终找到了合适的路径,并不是那么困难,所以我把我的解决方案贴出来,希望可以节省别人的时间。
npm install --save react-router-dom @types/react-router-dom
. { BrowserRouter, Route, RouteComponentProps, withRouter }
从 react-router-dom
.history
从 RouteComponentProps
通过解构。function MyComponent( { history }: ReactComponentProps) {
...
}
在屏幕状态改变时(用户认为是一个新的页面),在下面增加一个空白条目。history
;为例。
function MyComponent( { history }: ReactComponentProps) {
const handleClick() {
history.push('')
}
}
这将在历史记录中创建一个空白条目,所以历史记录中的条目可以被后退按钮访问;但用户看到的网址不会改变。
componentDidMount
在函数组件中不能工作。请确保 useEffect
是从 react
.)useEffect(() => {
// code here would fire when the page loads, equivalent to `componentDidMount`.
return () => {
// code after the return is equivalent to `componentWillUnmount`
if (history.action === "POP") {
// handle any state changes necessary to set the screen display back one page.
}
}
})
withRouter
并创建一个可以访问路由属性的新组件。const ComponentWithHistory = withRouter(MyComponent);
现在把所有的东西都包在一个 <BrowserRouter />
和a <Route />
以便React Router将其识别为路由器,并将所有路径路由到 path="/"
,它将捕获所有的路由,除非指定了更多的特定路径的路由(无论如何,这些路径都是一样的,在这种设置下,由于 history.push("")
; 历史将是这样的 ["", "", "", "", ""]
).
function App() {
return (
<BrowserRouter>
<Route path="/">
<ThemeProvider theme={theme}>
<ComponentWithHistory />
</ThemeProvider>
</Route>
</BrowserRouter>
);
}
export default App;
一个完整的例子现在看起来是这样的。
function MyComponent( { history }: ReactComponentProps) {
// use a state hook to manage a "page" state variable
const [page, setPage] = React.useState(0)
const handleClick() {
setPage(page + 1);
history.push('');
}
useEffect(() => {
return () => {
if (history.action === "POP") {
// set state back one to render previous "page" (state)
setPage(page - 1)
}
}
})
}
const ComponentWithHistory = withRouter(MyComponent);
function App() {
return (
<BrowserRouter>
<Route path="/">
<ThemeProvider theme={theme}>
<ComponentWithHistory />
</ThemeProvider>
</Route>
</BrowserRouter>
);
}
export default App;
如果有更好的方法,我很乐意听到;但这对我来说非常有效。