React状态管理的项目实践

 更新时间:2026年01月22日 10:39:16   作者:她的四晚饭  
本文主要介绍了状态管理的概念,包括本地状态和全局状态的管理方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

概念

状态管理是指如何高效地管理和共享组件中的状态。React 提供了 useStateuseReducer 来管理本地状态,而对于全局状态,可以使用 Context API 或第三方库(如 Redux)。

用法

  • 本地状态:使用 useState 或 useReducer
  • 全局状态:使用 Context API 或 Redux。

使用场景

  • 本地状态:组件内部的状态,如表单输入、按钮点击。
  • 全局状态:需要跨组件共享的状态,如用户登录信息、主题设置。

代码示例

// 1. 使用 Context API 管理全局状态
const ThemeContext = React.createContext('light');

function App() {
  const [theme, setTheme] = React.useState('light');

  const toggleTheme = () => {
    setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    <ThemeContext.Provider value={theme}>
      <Toolbar toggleTheme={toggleTheme} />
    </ThemeContext.Provider>
  );
}

function Toolbar({ toggleTheme }) {
  return (
    <div>
      <ThemedButton toggleTheme={toggleTheme} />
    </div>
  );
}

function ThemedButton({ toggleTheme }) {
  const theme = React.useContext(ThemeContext);

  return (
    <button
      onClick={toggleTheme}
      style={{ background: theme === 'dark' ? '#333' : '#fff', color: theme === 'dark' ? '#fff' : '#333' }}
    >
      Toggle Theme
    </button>
  );
}

代码解析

  • ThemeContext.Provider:提供全局状态 theme。
  • useContext:在子组件中获取 theme 状态。
  • toggleTheme:通过父组件传递回调函数来更新状态。

下面使用一个功能来说明状态管理的用法

实现功能

  1. 商品列表:显示用户可以购买的商品。
  2. 购物车:显示用户已添加的商品,并计算总价。
  3. 添加商品:用户点击商品时将其添加到购物车。
  4. 移除商品:用户可以点击按钮从购物车中移除商品。

代码实现

1. 创建CartContext管理全局状态

// src/contexts/CartContext.js
import React, { createContext, useReducer, useContext } from 'react';

// 创建 Context
const CartContext = createContext();

// 定义 initialState 初始状态
const initialState = {
  cartItems: [], // 购物车中的商品
};

// 定义 Reducer 函数,用于处理状态更新
function cartReducer(state, action) {
  switch (action.type) {
    case 'ADD_ITEM':
      // 检查商品是否已经存在于购物车中
      const existingItem = state.cartItems.find(item => item.id === action.payload.id);
      if (existingItem) {
        // 如果存在,更新数量
        return {
          ...state,
          cartItems: state.cartItems.map(item =>
            item.id === action.payload.id ? { ...item, quantity: item.quantity + 1 } : item
          ),
        };
      } else {
        // 如果不存在,添加新商品
        return {
          ...state,
          cartItems: [...state.cartItems, { ...action.payload, quantity: 1 }],
        };
      }
    case 'REMOVE_ITEM':
      // 移除商品
      return {
        ...state,
        cartItems: state.cartItems.filter(item => item.id !== action.payload.id),
      };
    default:
      return state;
  }
}

// 创建 Provider 组件,用于包裹应用并提供全局状态
export function CartProvider({ children }) {
  const [state, dispatch] = useReducer(cartReducer, initialState); // 使用 useReducer 管理状态

  return (
    <CartContext.Provider value={{ state, dispatch }}>
      {

2. 创建商品列表组件

// src/components/ProductList.js
import React from 'react';
import { useCart } from '../contexts/CartContext'; // 引入 useCart Hook

const products = [
  { id: 1, name: '商品 1', price: 10 },
  { id: 2, name: '商品 2', price: 20 },
  { id: 3, name: '商品 3', price: 30 },
];

function ProductList() {
  const { dispatch } = useCart(); // 获取 dispatch 函数

  const handleAddToCart = product => {
    dispatch({ type: 'ADD_ITEM', payload: product }); // 触发 ADD_ITEM 动作
  };

  return (
    <div>
      <h2>商品列表</h2>
      <ul>
        {products.map(product => (
          <li key={product.id}>
            {product.name} - ¥{product.price}
            <button onClick={() => handleAddToCart(product)}>添加到购物车</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default ProductList;

3. 创建购物车组件

// src/components/Cart.js
import React from 'react';
import { useCart } from '../contexts/CartContext'; // 引入 useCart Hook

function Cart() {
  const { state, dispatch } = useCart(); // 获取 state 和 dispatch

  const handleRemoveFromCart = item => {
    dispatch({ type: 'REMOVE_ITEM', payload: item }); // 触发 REMOVE_ITEM 动作
  };

  // 计算购物车总价
  const totalPrice = state.cartItems.reduce((total, item) => total + item.price * item.quantity, 0);

  return (
    <div>
      <h2>购物车</h2>
      {state.cartItems.length === 0 ? ( // 如果购物车为空,显示提示信息
        <p>购物车为空</p>
      ) : (
        <ul>
          {state.cartItems.map(item => (
            <li key={item.id}>
              {item.name} - ¥{item.price} x {item.quantity}
              <button onClick={() => handleRemoveFromCart(item)}>移除</button>
            </li>
          ))}
        </ul>
      )}
      <h3>总价: ¥{totalPrice}</h3>
    </div>
  );
}

export default Cart;

4. 在主应用中使用CartProvider包裹组件

// src/App.js
import React from 'react';
import { CartProvider } from './contexts/CartContext'; // 引入 CartProvider
import ProductList from './components/ProductList'; // 引入商品列表组件
import Cart from './components/Cart'; // 引入购物车组件

function App() {
  return (
    <CartProvider> // 使用 CartProvider 包裹应用,提供全局状态
      <div>
        <h1>购物车应用</h1>
        <ProductList />
        <Cart />
      </div>
    </CartProvider>
  );
}

export default App;

代码解析

  1. CartContext

    • 使用 createContext 创建上下文。
    • 使用 useReducer 管理状态,定义 ADD_ITEM 和 REMOVE_ITEM 两种动作。
    • CartProvider 包裹整个应用,提供全局状态。
  2. ProductList

    • 显示商品列表,点击按钮将商品添加到购物车。
    • 使用 dispatch 触发 ADD_ITEM 动作。
  3. Cart

    • 显示购物车中的商品和总价。
    • 使用 dispatch 触发 REMOVE_ITEM 动作。
  4. App

    • 使用 CartProvider 包裹应用,使全局状态在 ProductList 和 Cart 之间共享。

运行效果

  • 用户可以从商品列表中添加商品到购物车。
  • 购物车会显示已添加的商品和总价。
  • 用户可以点击“移除”按钮从购物车中删除商品。

总结

通过这个例子,我们学习了如何使用 Context APIuseReducer 管理全局状态:

  • 状态管理:将购物车的状态和逻辑集中管理。
  • 组件复用:商品列表和购物车组件各自独立,但共享相同的状态。
  • 代码结构清晰:将上下文、组件和主应用分离,易于维护和扩展。

通过模块化的方式进行管理实现

实现思路

  1. state:单独定义全局状态。
  2. actions:定义操作状态的函数。
  3. reducer:处理状态更新逻辑。
  4. store:创建 Redux store,集中管理状态。
  5. 组件:在其他组件中通过 useSelector 和 useDispatch 访问状态和触发动作。

代码实现

1. 定义state、actions和reducer

// src/store/cartSlice.js
import { createSlice } from '@reduxjs/toolkit'; // 使用 Redux Toolkit 简化代码

// 定义初始状态
const initialState = {
  cartItems: [], // 购物车中的商品
};

// 创建 slice,包含 reducer 和 actions
const cartSlice = createSlice({
  name: 'cart', // slice 名称
  initialState, // 初始状态
  reducers: {
    // 添加商品的 reducer
    addItem: (state, action) => {
      const existingItem = state.cartItems.find(item => item.id === action.payload.id);
      if (existingItem) {
        existingItem.quantity += 1; // 如果商品已存在,增加数量
      } else {
        state.cartItems.push({ ...action.payload, quantity: 1 }); // 如果不存在,添加新商品
      }
    },
    // 移除商品的 reducer
    removeItem: (state, action) => {
      state.cartItems = state.cartItems.filter(item => item.id !== action.payload.id);
    },
  },
});

// 导出 actions
export const { addItem, removeItem } = cartSlice.actions;

// 导出 reducer
export default cartSlice.reducer;

2. 创建store,集中管理状态

// src/store/store.js
import { configureStore } from '@reduxjs/toolkit'; // 使用 Redux Toolkit 简化代码
import cartReducer from './cartSlice'; // 引入 cartReducer

// 创建 store
const store = configureStore({
  reducer: {
    cart: cartReducer, // 将 cartReducer 挂载到 store
  },
});

export default store;

3. 在主应用中使用Provider包裹组件

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'; // 引入 Provider
import store from './store/store'; // 引入 store
import App from './App';

ReactDOM.render(
  <Provider store={store}> {/* 使用 Provider 包裹应用,传递 store */}
    <App />
  </Provider>,
  document.getElementById('root')
);

4. 创建商品列表组件

// src/components/ProductList.js
import React from 'react';
import { useDispatch } from 'react-redux'; // 引入 useDispatch
import { addItem } from '../store/cartSlice'; // 引入 addItem action

const products = [
  { id: 1, name: '商品 1', price: 10 },
  { id: 2, name: '商品 2', price: 20 },
  { id: 3, name: '商品 3', price: 30 },
];

function ProductList() {
  const dispatch = useDispatch(); // 获取 dispatch 函数

  const handleAddToCart = product => {
    dispatch(addItem(product)); // 触发 addItem action
  };

  return (
    <div>
      <h2>商品列表</h2>
      <ul>
        {products.map(product => (
          <li key={product.id}>
            {product.name} - ¥{product.price}
            <button onClick={() => handleAddToCart(product)}>添加到购物车</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default ProductList;

5. 创建购物车组件

// src/components/Cart.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux'; // 引入 useSelector 和 useDispatch
import { removeItem } from '../store/cartSlice'; // 引入 removeItem action

function Cart() {
  const cartItems = useSelector(state => state.cart.cartItems); // 获取购物车商品
  const dispatch = useDispatch(); // 获取 dispatch 函数

  const handleRemoveFromCart = item => {
    dispatch(removeItem(item)); // 触发 removeItem action
  };

  // 计算购物车总价
  const totalPrice = cartItems.reduce((total, item) => total + item.price * item.quantity, 0);

  return (
    <div>
      <h2>购物车</h2>
      {cartItems.length === 0 ? ( // 如果购物车为空,显示提示信息
        <p>购物车为空</p>
      ) : (
        <ul>
          {cartItems.map(item => (
            <li key={item.id}>
              {item.name} - ¥{item.price} x {item.quantity}
              <button onClick={() => handleRemoveFromCart(item)}>移除</button>
            </li>
          ))}
        </ul>
      )}
      <h3>总价: ¥{totalPrice}</h3>
    </div>
  );
}

export default Cart;

6. 主应用组件

// src/App.js
import React from 'react';
import ProductList from './components/ProductList'; // 引入商品列表组件
import Cart from './components/Cart'; // 引入购物车组件

function App() {
  return (
    <div>
      <h1>购物车应用</h1>
      <ProductList />
      <Cart />
    </div>
  );
}

export default App;

 在这个例子中,Redux 中公共管理的状态是定义在 cartSlice.js 中的 initialState,具体是:

const initialState = { cartItems: [], // 购物车中的商品};

  1. cartItems

    • 这是一个数组,用于存储用户添加到购物车中的商品。
    • 每件商品是一个对象,包含以下属性:
      • id:商品的唯一标识。
      • name:商品名称。
      • price:商品价格。
      • quantity:商品的数量。
  2. 全局状态

    • 在 Redux 中,initialState 是这个 slice(模块)的初始状态。
    • 这个状态通过 store.js 挂载到 Redux 的全局状态树中。
    • 其他组件可以通过 useSelector 访问这个状态,也可以通过 useDispatch 触发动作来修改这个状态。

代码解析

  1. cartSlice.js:

    • 使用 Redux Toolkit 的 createSlice 定义 state、reducer 和 actions。
    • addItem:添加商品到购物车,如果商品已存在则增加数量。
    • removeItem:从购物车中移除商品。
  2. store.js:

    • 使用 configureStore 创建 Redux store。
    • 将 cartSlice 的 reducer 挂载到 store。
  3. ProductList.js:

    • 使用 useDispatch 触发 addItem 动作,将商品添加到购物车。
  4. Cart.js:

    • 使用 useSelector 获取购物车中的商品。
    • 使用 useDispatch 触发 removeItem 动作,移除商品。
  5. App.js:

    • 展示商品列表和购物车组件。

总结

通过这种方式,我们实现了类似 Vuex 的状态管理结构:

  • state 和 actions 单独抽离,模块化管理。
  • 使用 Redux Toolkit 简化了 Redux 的代码。
  • 在组件中通过 useSelector 和 useDispatch 访问和操作状态。

这种模式非常适合大型应用的状态管理,代码结构清晰,易于维护和扩展。 😊

到此这篇关于React状态管理的项目实践的文章就介绍到这了,更多相关React状态管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解react-router 4.0 下服务器如何配合BrowserRouter

    详解react-router 4.0 下服务器如何配合BrowserRouter

    这篇文章主要介绍了详解react-router 4.0 下服务器如何配合BrowserRouter,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • React class 的组件库与函数组件适配集成方案

    React class 的组件库与函数组件适配集成方案

    这篇文章主要介绍了React class 的组件库与函数组件适配集成方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-05-05
  • Remix路由模块输出对象loader函数详解

    Remix路由模块输出对象loader函数详解

    这篇文章主要为大家介绍了Remix路由模块输出对象loader函数详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2023-04-04
  • React中的生命周期用法详解

    React中的生命周期用法详解

    这篇文章主要介绍了React中的生命周期用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • React+ResizeObserver实现自适应ECharts图表

    React+ResizeObserver实现自适应ECharts图表

    ResizeObserver是JavaScript的一个API,用于监测元素的大小变化,本文主要为大家介绍了React如何利用ResizeObserver实现自适应ECharts图表,需要的可以参考下
    2024-01-01
  • React之防止按钮多次点击事件 重复提交

    React之防止按钮多次点击事件 重复提交

    这篇文章主要介绍了React之防止按钮多次点击事件 重复提交问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • react中如何对自己的组件使用setFieldsValue

    react中如何对自己的组件使用setFieldsValue

    react中如何对自己的组件使用setFieldsValue问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • React18的useEffect执行两次如何应对

    React18的useEffect执行两次如何应对

    这篇文章主要给大家介绍了关于React18的useEffect执行两次如何应对的相关资料,文中通过实例代码介绍的非常详细,对大家学习或者使用React具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • 详解react、redux、react-redux之间的关系

    详解react、redux、react-redux之间的关系

    这篇文章主要介绍了详解react、redux、react-redux之间的关系,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • React 组件通信的多种方式与最佳实践

    React 组件通信的多种方式与最佳实践

    在现代前端开发中,组件化是 React 的核心理念之一,组件之间的通信是构建复杂应用的重要组成部分,在这篇文章中,我们将深入探讨 React 组件通信的多种方式,包括它们的优缺点、使用场景以及最佳实践,需要的朋友可以参考下
    2024-11-11

最新评论