MST

星途 面试题库

面试题:React Router历史记录操作在复杂路由嵌套场景下的应用

假设有一个多层嵌套的React Router路由结构,如 /parent/child/grandchild 这样的层级关系,在grandchild页面中,如何通过历史记录操作,直接返回到parent页面,并确保页面状态正确恢复,且不引起不必要的重新渲染?请阐述思路并写出关键代码逻辑。
22.0万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

思路

  1. 在React Router中,history对象提供了操作历史记录的方法。要从grandchild页面返回到parent页面,可以使用history.goBack()或者history.push()方法。
  2. 为了确保页面状态正确恢复且不引起不必要的重新渲染,我们可以利用React Router的路由参数或者状态管理工具(如Redux)来保存和恢复状态。在这种情况下,由于没有提及使用状态管理工具,我们可以通过路由参数来实现。

关键代码逻辑

  1. 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;
    
  2. 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;
    
  3. 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等优化方式)。