MST

星途 面试题库

面试题:Next.js 嵌套路由多级菜单的动态数据加载与状态管理

假设在一个多级菜单应用里,菜单选项的数据来自后端 API。在 Next.js 嵌套路由场景下,如何在页面加载时根据当前路由动态获取对应菜单数据,并使用 React 的状态管理方案(如 Redux 或 React Context)来管理这些数据,以确保各级菜单之间数据的一致性和交互的流畅性,请阐述实现思路并给出关键代码示例。
39.6万 热度难度
前端开发Next.js

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 路由匹配与 API 调用:在 Next.js 的嵌套路由中,利用 useRouter 钩子获取当前路由信息。根据路由信息构建请求参数,调用后端 API 获取对应的菜单数据。
  2. 状态管理
    • Redux:将获取到的菜单数据存入 Redux store。通过 action 来触发数据的获取和更新。在组件中使用 connect 或者 useSelectoruseDispatch 钩子来连接组件与 store,确保数据一致性。
    • React Context:创建一个上下文对象,在顶层组件中提供该上下文,将菜单数据作为上下文的值。各级子组件通过 useContext 钩子来获取和更新数据,保持数据一致性。
  3. 数据一致性与交互流畅性:通过状态管理方案,确保各级菜单使用相同数据源。当数据更新时,所有依赖该数据的组件会自动重新渲染,保证交互流畅性。

关键代码示例

使用 Redux

  1. 安装依赖
    npm install redux react-redux
    
  2. 创建 Redux store 和 actions
    // store.js
    import { createStore } from'redux';
    const initialState = { menuData: [] };
    const menuReducer = (state = initialState, action) => {
      switch (action.type) {
        case 'FETCH_MENU_SUCCESS':
          return {
            ...state,
            menuData: action.payload
          };
        default:
          return state;
      }
    };
    const store = createStore(menuReducer);
    export default store;
    
    // actions.js
    import { FETCH_MENU_SUCCESS } from './actionTypes';
    import axios from 'axios';
    export const fetchMenuData = () => async (dispatch) => {
      try {
        const response = await axios.get('/api/menu');
        dispatch({ type: FETCH_MENU_SUCCESS, payload: response.data });
      } catch (error) {
        console.error('Error fetching menu data:', error);
      }
    };
    
  3. 在 Next.js 页面中使用
    // pages/[...menu].js
    import React from'react';
    import { useRouter } from 'next/router';
    import { useSelector, useDispatch } from'react-redux';
    import { fetchMenuData } from '../actions';
    const MenuPage = () => {
      const router = useRouter();
      const menuData = useSelector((state) => state.menuData);
      const dispatch = useDispatch();
      React.useEffect(() => {
        dispatch(fetchMenuData());
      }, [dispatch]);
      return (
        <div>
          {/* 渲染菜单数据 */}
        </div>
      );
    };
    export default MenuPage;
    

使用 React Context

  1. 创建 Context
    // MenuContext.js
    import React from'react';
    const MenuContext = React.createContext();
    export default MenuContext;
    
  2. 在顶层组件中提供 Context
    // _app.js
    import React, { useState, useEffect } from'react';
    import MenuContext from '../MenuContext';
    import axios from 'axios';
    const MyApp = ({ Component, pageProps }) => {
      const [menuData, setMenuData] = useState([]);
      useEffect(() => {
        const fetchMenu = async () => {
          try {
            const response = await axios.get('/api/menu');
            setMenuData(response.data);
          } catch (error) {
            console.error('Error fetching menu data:', error);
          }
        };
        fetchMenu();
      }, []);
      return (
        <MenuContext.Provider value={menuData}>
          <Component {...pageProps} />
        </MenuContext.Provider>
      );
    };
    export default MyApp;
    
  3. 在子组件中使用 Context
    // pages/[...menu].js
    import React from'react';
    import { useRouter } from 'next/router';
    import MenuContext from '../MenuContext';
    const MenuPage = () => {
      const router = useRouter();
      const menuData = React.useContext(MenuContext);
      return (
        <div>
          {/* 渲染菜单数据 */}
        </div>
      );
    };
    export default MenuPage;