如何在含Link组件的react-router中使用CSSTransition?
解决React路由组件无法触发CSSTransition状态更新的问题
方法一:通过Props传递状态更新函数
直接将setIsEnter作为props传入每个路由组件,子组件接收后即可调用。
- 修改
routes.js,给路由元素传递setIsEnter:
const Routes = () => { const [isEnter, setIsEnter] = useState(false) return( <CSSTransition in={isEnter} timeout={4000} classNames='fade' unmountOnExit > <Router> <Routes> <Route exact path='/' element={<StartPage setIsEnter={setIsEnter} />} /> <Route path='/question-one' element={<FirstQuestion setIsEnter={setIsEnter} />} /> <Route path='/question-two' element={<FavoritePerson setIsEnter={setIsEnter} />} /> {/* 其余路由按此格式添加props */} </Routes> </Router> </CSSTransition> ) } export default Routes;
- 修改
StartPage.js,接收并调用props中的setIsEnter:
export default function StartPage({ setIsEnter }) { const handleNavigate = () => { // 根据动画逻辑切换状态,这里取反示例 setIsEnter(prev => !prev); }; return ( <div className="card"> <h1 className='card-title'>Está pronta?</h1> <form> <Link to='/question-one' className='button-submit' onClick={handleNavigate}> SIM </Link> <input type='button' value='NÂO' onClick={warningMessage}></input> </form> </div> ); }
方法二:使用React Context全局共享状态
如果路由组件数量较多,逐个传props效率低,可通过Context全局共享状态及更新函数。
- 创建
TransitionContext.js文件:
import { createContext, useContext, useState } from 'react'; const TransitionContext = createContext(); export function TransitionProvider({ children }) { const [isEnter, setIsEnter] = useState(false); return ( <TransitionContext.Provider value={{ isEnter, setIsEnter }}> {children} </TransitionContext.Provider> ); } export function useTransition() { return useContext(TransitionContext); }
- 修改
routes.js,用TransitionProvider包裹并获取Context状态:
import { TransitionProvider, useTransition } from './TransitionContext'; const RoutesWrapper = () => { return ( <TransitionProvider> <Routes /> </TransitionProvider> ); }; const Routes = () => { const { isEnter, setIsEnter } = useTransition(); return( <CSSTransition in={isEnter} timeout={4000} classNames='fade' unmountOnExit > <Router> <Routes> <Route exact path='/' element={<StartPage />} /> {/* 其余路由无需再传props */} </Routes> </Router> </CSSTransition> ) } export default RoutesWrapper;
- 修改
StartPage.js,通过useTransition获取更新函数:
import { useTransition } from './TransitionContext'; export default function StartPage() { const { setIsEnter } = useTransition(); const handleNavigate = () => { setIsEnter(prev => !prev); }; return ( <div className="card"> <h1 className='card-title'>Está pronta?</h1> <form> <Link to='/question-one' className='button-submit' onClick={handleNavigate}> SIM </Link> <input type='button' value='NÂO' onClick={warningMessage}></input> </form> </div> ); }
方法三:自定义过渡Link组件
创建集成状态更新逻辑的自定义Link,替换原生Link,无需每个页面单独处理点击事件。
- 创建
TransitionLink.js文件:
import { Link } from 'react-router-dom'; import { useTransition } from './TransitionContext'; export default function TransitionLink({ to, children, ...props }) { const { setIsEnter } = useTransition(); const handleClick = () => { setIsEnter(prev => !prev); }; return ( <Link to={to} {...props} onClick={handleClick}> {children} </Link> ); }
- 在
StartPage.js中使用自定义Link:
import TransitionLink from './TransitionLink'; export default function StartPage() { return ( <div className="card"> <h1 className='card-title'>Está pronta?</h1> <form> <TransitionLink to='/question-one' className='button-submit'> SIM </TransitionLink> <input type='button' value='NÂO' onClick={warningMessage}></input> </form> </div> ); }
内容的提问来源于stack exchange,提问作者Gustavo Gomes
相关产品推荐
相关产品推荐

