面试题答案
一键面试思路
- 在React Router中,
history
对象提供了操作历史记录的方法。要从grandchild
页面返回到parent
页面,可以使用history.goBack()
或者history.push()
方法。 - 为了确保页面状态正确恢复且不引起不必要的重新渲染,我们可以利用
React Router
的路由参数或者状态管理工具(如Redux
)来保存和恢复状态。在这种情况下,由于没有提及使用状态管理工具,我们可以通过路由参数来实现。
关键代码逻辑
- 在
parent
组件中:- 当跳转到
grandchild
页面时,将当前parent
页面的状态作为参数传递。
import React from'react'; import { Link } from'react-router-dom'; const Parent = () => { const parentState = { someData: 'example' }; return ( <div> <h1>Parent Page</h1> <Link to={{ pathname: '/parent/child/grandchild', state: { parentState } }}> Go to Grandchild </Link> </div> ); }; export default Parent;
- 当跳转到
- 在
grandchild
组件中:- 获取传递过来的
parent
页面状态,并在返回时使用history.push()
方法回到parent
页面,并带上该状态。
import React from'react'; import { useHistory, useLocation } from'react-router-dom'; const Grandchild = () => { const history = useHistory(); const location = useLocation(); const { parentState } = location.state || {}; const goBackToParent = () => { history.push({ pathname: '/parent', state: { parentState } }); }; return ( <div> <h1>Grandchild Page</h1> <button onClick={goBackToParent}>Go Back to Parent</button> </div> ); }; export default Grandchild;
- 获取传递过来的
- 在
parent
组件再次渲染时:- 从路由状态中恢复之前保存的状态。
import React, { useState, useEffect } from'react'; import { useLocation } from'react-router-dom'; const Parent = () => { const [parentState, setParentState] = useState({}); const location = useLocation(); useEffect(() => { if (location.state && location.state.parentState) { setParentState(location.state.parentState); } }, [location.state]); return ( <div> <h1>Parent Page</h1> {/* 其他内容 */} </div> ); }; export default Parent;
通过这种方式,在从grandchild
页面返回到parent
页面时,能够正确恢复parent
页面的状态,并且由于我们是通过history.push()
并携带状态的方式,不会引起不必要的重新渲染(只要组件正确实现了shouldComponentUpdate
或者使用React.memo
等优化方式)。