如何在单击浏览器的后退按钮时防止页面CSS转换



我有一个简单的页面转换,它在单击链接时被调用。新页面从屏幕底部向上到顶部设置动画。它工作得很好,但当你在浏览器中单击后退按钮时,它也能工作。如果有人点击浏览器上的后退按钮,我不希望转换启动,我只想回到我留下的任何滚动位置的页面,就像点击浏览器后退按钮一样。

如果我去掉了CSS转换,那么后退按钮就可以正常工作,所以我需要以某种方式区分被点击的后退按钮和被点击的链接,然后相应地播放转换。

我不知道我是需要设置State还是其他什么?我确实尝试过,但它似乎在转换发生后设置了状态变量。

import React, { useEffect, useState }  from 'react';
import {Route, NavLink, Switch, useHistory } from "react-router-dom";
import './App.css';
import Home from './Home';
import About from './About';
import { CSSTransition, TransitionGroup,} from 'react-transition-group';


const usePageMeta = (title, description) =>{
const defaultTitle = "app-name";
const defaultDesc = "meta description";

useEffect(() => {
document.title = title || defaultTitle;
document.querySelector("meta[name='description']").setAttribute("content", description || defaultDesc);
}, [defaultTitl

e, title, defaultDesc, description]);
};

const App = () =>{


return (
<div className="App">
<div className="nav fixed top-0 left-0 z-10 w-full">
<NavLink exact to="/" activeClassName="active">Home</NavLink>
<NavLink to="/about"  activeClassName="active">About</NavLink>


</div>


<Route render={({location}) => (


<TransitionGroup>
<CSSTransition
key={location.key}
timeout={1000}
classNames="fade"

>
<Switch location={location}>
<Route exact path="/">
<Home usePageMeta={usePageMeta}/>
</Route>
<Route path="/about">
<About usePageMeta={usePageMeta}/>
</Route>
</Switch>
</CSSTransition>
</TransitionGroup>


)} />


</div>


);


}

export default App;

有人能给我指正确的方向吗?

经过一些测试,我可以看到,当路径被加载到浏览器的历史记录中时,这种情况必然会发生。

tl;dr这不是库的怪癖,只是浏览器的工作方式。当前会话总是在历史对象上推送状态。为了防止这种情况,你可以做两件事

  • 每当用户导航到新路径时,覆盖历史状态
  • 阻止后退按钮的默认操作并重定向到入口网站

解决方案1:

  1. 从"history"包导入createBrowserHistory,并在应用程序组件外部创建一个可变的history
  2. 使用history.createHref(history.location)进入应用程序时,使启动状态的字符串不可变
  3. 定义一个onClick处理程序,将历史记录的顶部状态替换为当前位置
  4. 使用上面定义的函数在两个NavLinks上注册一个点击处理程序
  5. 在历史记录中添加一个监听器(history.listen(,如果操作是pop,则调用history.goBack((
  6. 在卸载时调用unlisten
import { createBrowserHistory } from 'history';
let history = createBrowserHistory();
const ContainerComponent = () => {
// removed uselocation and usehistory hooks

const location = history.createHref(history.location);

const replaceHistory = () => {
history.replace(location);
}
const unlisten = history.listen((location, action) => {
if (action == "POP")
history.goBack();
})
useEffect(() => {
return () => unlisten();
})
return (
<div>
<Navlink to='/' onClick={replaceHistory} />
<Navlink to='/about' onClick={replaceHistory} />
</div>
);
}

解决方案2:

  1. 从"history"模块导入createBrowserHistory,并在应用程序组件外部创建一个可变历史对象
  2. 将监听器添加到历史记录(history.listen(中,当它接收到"-";POP";行动
  3. 使用Effect"取消收听"此事件

注意:这是假设用户必须导航到来自的网站。

import { createBrowserHistory } from 'history';
// Creates a mutable history state.
let history = createBrowserHistory();
const ContainerComponent = () => {
//removed the eventlistener on window

const unlisten() = history.listen((location, action) => {
//remove the logging once satisfied with the result.
console.log(`${location}, ${action}`);
if ( action == "POP" ) {
history.goBack();
}
})

// removed 'popstate' evenhandler

// adding useEffect to call unlisten on unmount
useEffect (() => {
return () => unlisten();
}, [])
const count = () => {
setPageChanges(pageChanges + 1);
}
return (
<div>
<NavLink to='/' onClick={count} />
<NavLink to='/about' onClick={count} />
</div>
{/*... rest of the switch code with the transition ...*/}
);
}

编辑:解决方案2被重构为使用"历史"包实用程序。这被认为是更合适的,因为浏览器状态不与react代码接触。

同样在文档中,提到历史对象是可变的,这确实会导致安装方面的一些问题。

注意:这个解决方案会遍历用户所在位置和开始位置之间的所有状态,所以可以期待早期组件的一些闪光。

解决方案1也使用相同的包,但需要注意的是,它将转到第一页,然后再转到goBack((1页。这将是比解决方案2更少的闪光。

最新更新