MST

星途 面试题库

面试题:React路由的性能优化及异常处理

在一个大型React应用中,路由数量众多且存在复杂的嵌套关系。请详细说明如何对路由进行性能优化,比如避免不必要的组件重渲染,减少首屏加载时间等。同时,阐述如何处理路由加载过程中的异常情况,如网络错误、路由未找到等,并且给出相应的代码示例及优化策略。
24.9万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

路由性能优化

  1. 避免不必要的组件重渲染
    • 使用 React.memo 或 PureComponent:对于展示型组件,用 React.memo(函数组件)或 PureComponent(类组件)包裹。它们会浅比较 props,如果 props 没有变化,组件不会重新渲染。
    const MyComponent = React.memo((props) => {
      return <div>{props.value}</div>;
    });
    
    • 减少 context 使用的范围:如果使用 Context,尽量缩小其作用域,只在真正需要的组件树部分使用。因为 Context 的变化会导致所有使用该 Context 的组件重新渲染。
    • 合理使用 useCallback 和 useMemouseCallback 用于缓存函数,useMemo 用于缓存值。例如,当传递给子组件的函数依赖于一些状态,但状态变化时并不希望子组件因函数引用变化而重渲染,就可以用 useCallback
    const [count, setCount] = useState(0);
    const handleClick = useCallback(() => {
      setCount(count + 1);
    }, [count]);
    
  2. 减少首屏加载时间
    • 代码分割:使用动态导入(import())实现路由组件的代码分割。这样只有在路由被访问时才会加载相应的组件代码,而不是在首屏就加载所有路由组件。
    const routes = [
      {
        path: '/home',
        component: React.lazy(() => import('./Home')),
      },
      {
        path: '/about',
        component: React.lazy(() => import('./About')),
      },
    ];
    
    • 预加载:结合 React.lazySuspense,可以在适当的时候预加载路由组件。例如,在用户可能会访问的路由附近,提前调用 import() 进行预加载。
    const Home = React.lazy(() => import('./Home'));
    useEffect(() => {
      // 预加载 Home 组件
      React.lazy(() => import('./Home'));
    }, []);
    
    • 优化网络请求:对于路由组件依赖的 API 请求,使用缓存机制,避免重复请求相同的数据。可以使用 fetchcache 选项,或者自己实现简单的内存缓存。
    const cache = {};
    const fetchData = async (url) => {
      if (cache[url]) {
        return cache[url];
      }
      const response = await fetch(url);
      const data = await response.json();
      cache[url] = data;
      return data;
    };
    

处理路由加载异常情况

  1. 网络错误
    • 在路由组件内处理:在路由组件的生命周期(类组件)或 useEffect(函数组件)中进行网络请求,并处理错误。
    const MyRouteComponent = () => {
      const [data, setData] = useState(null);
      const [error, setError] = useState(null);
      useEffect(() => {
        const fetchData = async () => {
          try {
            const response = await fetch('/api/data');
            if (!response.ok) {
              throw new Error('Network response was not ok');
            }
            const result = await response.json();
            setData(result);
          } catch (error) {
            setError(error);
          }
        };
        fetchData();
      }, []);
      if (error) {
        return <div>Error: {error.message}</div>;
      }
      if (!data) {
        return <div>Loading...</div>;
      }
      return <div>{JSON.stringify(data)}</div>;
    };
    
  2. 路由未找到
    • 设置通配符路由:在路由配置中设置一个通配符路由(如 *),当没有匹配到任何路由时,展示 404 页面。
    const routes = [
      {
        path: '/home',
        component: Home,
      },
      {
        path: '*',
        component: NotFound,
      },
    ];
    
    • 自定义错误边界:可以创建一个自定义错误边界组件,捕获路由组件渲染、生命周期方法或构造函数中抛出的错误,并进行统一处理,如显示友好的错误提示。
    class ErrorBoundary extends React.Component {
      constructor(props) {
        super(props);
        this.state = { hasError: false };
      }
      componentDidCatch(error, errorInfo) {
        console.log('Error in route component:', error, errorInfo);
        this.setState({ hasError: true });
      }
      render() {
        if (this.state.hasError) {
          return <div>An error occurred in the route component.</div>;
        }
        return this.props.children;
      }
    }
    
    • 在路由配置中使用错误边界
    const routes = [
      {
        path: '/home',
        component: () => (
          <ErrorBoundary>
            <Home />
          </ErrorBoundary>
        ),
      },
    ];