You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React 18类组件结合Redux页面加载时获取数据的最佳实践

在React 18类组件中结合Redux实现导航菜单数据加载

1. 配置Redux异步中间件(必要前提)

要在Action里调用异步API,需依赖redux-thunk中间件。先安装:

npm install redux-thunk

创建Store时启用该中间件:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

export default store;

2. 定义Action Types

用常量定义Action类型,避免拼写错误:

// src/actions/menuActionTypes.js
export const FETCH_MENU_REQUEST = 'FETCH_MENU_REQUEST';
export const FETCH_MENU_SUCCESS = 'FETCH_MENU_SUCCESS';
export const FETCH_MENU_FAILURE = 'FETCH_MENU_FAILURE';

3. 创建Action Creators

编写处理异步请求的Action Creator,包含API调用逻辑:

// src/actions/menuActions.js
import { FETCH_MENU_REQUEST, FETCH_MENU_SUCCESS, FETCH_MENU_FAILURE } from './menuActionTypes';

// 异步Action Creator,返回函数而非普通对象
export const fetchMenu = () => {
  return async (dispatch) => {
    dispatch({ type: FETCH_MENU_REQUEST });
    try {
      // 替换为你的实际后端API地址
      const response = await fetch('/api/nav-menu');
      const menuData = await response.json();
      dispatch({ 
        type: FETCH_MENU_SUCCESS, 
        payload: menuData 
      });
    } catch (err) {
      dispatch({ 
        type: FETCH_MENU_FAILURE, 
        payload: err.message 
      });
    }
  };
};

4. 编写Menu Reducer

创建Reducer处理Action,维护菜单相关状态:

// src/reducers/menuReducer.js
import { FETCH_MENU_REQUEST, FETCH_MENU_SUCCESS, FETCH_MENU_FAILURE } from '../actions/menuActionTypes';

const initialState = {
  loading: false,
  menuItems: [],
  error: ''
};

const menuReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_MENU_REQUEST:
      return { ...state, loading: true };
    case FETCH_MENU_SUCCESS:
      return {
        loading: false,
        menuItems: action.payload,
        error: ''
      };
    case FETCH_MENU_FAILURE:
      return {
        loading: false,
        menuItems: [],
        error: action.payload
      };
    default:
      return state;
  }
};

export default menuReducer;

将该Reducer合并到根Reducer(若有多个Reducer):

// src/reducers/index.js
import { combineReducers } from 'redux';
import menuReducer from './menuReducer';

const rootReducer = combineReducers({
  menu: menuReducer
});

export default rootReducer;

5. 在类组件中实现数据加载

利用componentDidMount生命周期触发API请求,通过connect关联Redux Store与组件:

// src/components/Navigation.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchMenu } from '../actions/menuActions';

class Navigation extends Component {
  componentDidMount() {
    // 页面加载时触发菜单数据请求
    this.props.fetchMenu();
  }

  render() {
    const { loading, menuItems, error } = this.props;

    return (
      <nav className="nav-container">
        {loading && <div className="loading">加载中...</div>}
        {error && <div className="error">加载失败:{error}</div>}
        {!loading && !error && (
          <ul className="menu-list">
            {menuItems.map(item => (
              <li key={item.id} className="menu-item">
                <a href={item.url}>{item.title}</a>
              </li>
            ))}
          </ul>
        )}
      </nav>
    );
  }
}

// 将Store中的菜单状态映射到组件props
const mapStateToProps = state => ({
  loading: state.menu.loading,
  menuItems: state.menu.menuItems,
  error: state.menu.error
});

// 将Action Creator映射到组件props
const mapDispatchToProps = dispatch => ({
  fetchMenu: () => dispatch(fetchMenu())
});

// 连接组件与Redux Store
export default connect(mapStateToProps, mapDispatchToProps)(Navigation);

最佳实践要点

  • Action类型用常量:避免硬编码字符串引发的错误,便于统一管理。
  • Reducer保持纯函数:禁止在Reducer内执行异步操作、修改原state,必须返回新的state对象。
  • 处理加载/错误状态:给用户明确的状态反馈,避免页面空白或无响应的糟糕体验。
  • 组件与Redux解耦:通过connect映射状态与动作,组件仅负责渲染和触发动作,不直接操作Store。
  • API逻辑封装:若多个组件需调用菜单API,建议将请求逻辑封装到单独的service文件,Action Creator仅负责调度动作。

内容的提问来源于stack exchange,提问作者ethanm912

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 11:05:27