最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

react中多個頁面,數(shù)據(jù)相互依賴reducer問題及解決

 更新時間:2025年12月20日 15:52:02   作者:初遇你時動了情  
文章介紹了一個電商商品管理頁面的復(fù)雜狀態(tài)管理場景,使用useReducer或useImmerReducer來集中管理狀態(tài),避免組件間直接監(jiān)聽,簡化聯(lián)動邏輯,防止死循環(huán),并便于維護(hù)和擴(kuò)展

場景

典型的電商商品管理頁面復(fù)雜狀態(tài)場景,涉及多個模塊數(shù)據(jù)聯(lián)動、動態(tài)生成 SKU、屬性和額外參數(shù)注入等。關(guān)鍵點(diǎn)是 避免組件之間直接相互監(jiān)聽,保持邏輯集中化

頁面模塊

  • 基本信息
  • 商品名稱
  • 分類 / 平臺分類
  • 詳細(xì)信息(富文本/描述)
  • 規(guī)格名稱、規(guī)格值
  • SKU 列表:基于規(guī)格動態(tài)生成
  • SKU 可能包含額外字段(如價格、庫存、額外參數(shù))
  • 動態(tài)數(shù)據(jù)依賴

切換平臺分類 → 獲取動態(tài)屬性、額外參數(shù) → 注入到 SKU

修改規(guī)格名稱 → 重新生成 SKU

核心問題:

  • SKU 生成依賴規(guī)格數(shù)據(jù)、額外參數(shù)
  • 額外參數(shù)依賴平臺分類
  • 數(shù)據(jù)變化涉及多個模塊聯(lián)動,容易出現(xiàn)重復(fù)計算或死循環(huán)

useReducer(或者 useImmerReducer) 比直接在組件里用一堆 useState + useEffect 更適合,原因如下:

  • 集中管理狀態(tài):所有頁面狀態(tài)都在一個地方管理,組件只負(fù)責(zé)渲染和觸發(fā)操作。
  • 統(tǒng)一處理聯(lián)動邏輯:SKU 生成、額外參數(shù)注入、動態(tài)屬性拉取都在 reducer 內(nèi)完成,不會散落在各組件的 useEffect 里。
  • 避免死循環(huán):不需要組件間相互監(jiān)聽狀態(tài)變化,更新邏輯集中在 reducer 內(nèi)部。
  • 便于維護(hù)和擴(kuò)展:新增字段或聯(lián)動規(guī)則,只需改 reducer,不用改每個組件

狀態(tài)設(shè)計

import { useReducer } from 'react';
import produce from 'immer';

interface ProductState {
  basicInfo: {
    name: string;
    categoryId: number;
    platformCategoryId: number;
    description: string;
  };
  specs: {
    name: string;
    values: string[];
  }[];
  dynamicAttributes: Record<string, any>; // 平臺分類動態(tài)屬性
  extraParams: Record<string, any>;       // 平臺分類額外參數(shù)
  skuList: SKU[];
}

interface SKU {
  id?: string;
  specCombination: string[]; // 每個SKU對應(yīng)的規(guī)格值組合
  price: number;
  stock: number;
  extraParams?: Record<string, any>;
}

const initialState: ProductState = {
  basicInfo: {
    name: '',
    categoryId: 0,
    platformCategoryId: 0,
    description: ''
  },
  specs: [],
  dynamicAttributes: {},
  extraParams: {},
  skuList: []
};

Reducer 設(shè)計(包含聯(lián)動邏輯)

type Action =
  | { type: 'UPDATE_BASIC_INFO'; payload: Partial<ProductState['basicInfo']> }
  | { type: 'UPDATE_SPEC'; payload: { index: number; spec: Partial<ProductState['specs'][0]> } }
  | { type: 'SET_PLATFORM_CATEGORY'; payload: { platformCategoryId: number; dynamicAttributes: any; extraParams: any } }
  | { type: 'UPDATE_SKU'; payload: SKU[] };

function generateSKUList(specs: ProductState['specs'], extraParams: ProductState['extraParams']): SKU[] {
  // 簡化示例:生成規(guī)格組合的笛卡爾積
  if (specs.length === 0) return [];
  
  function cartesian(arrays: string[][]): string[][] {
    return arrays.reduce<string[][]>(
      (a, b) => a.flatMap(d => b.map(e => [...d, e])),
      [[]]
    );
  }

  const specValues = specs.map(s => s.values.length ? s.values : ['']);
  const combinations = cartesian(specValues);

  return combinations.map(comb => ({
    specCombination: comb,
    price: 0,
    stock: 0,
    extraParams: { ...extraParams }
  }));
}

function productReducer(state: ProductState, action: Action): ProductState {
  switch (action.type) {
    case 'UPDATE_BASIC_INFO':
      return { ...state, basicInfo: { ...state.basicInfo, ...action.payload } };

    case 'UPDATE_SPEC':
      return produce(state, draft => {
        draft.specs[action.payload.index] = { ...draft.specs[action.payload.index], ...action.payload.spec };
        draft.skuList = generateSKUList(draft.specs, draft.extraParams);
      });

    case 'SET_PLATFORM_CATEGORY':
      return produce(state, draft => {
        draft.basicInfo.platformCategoryId = action.payload.platformCategoryId;
        draft.dynamicAttributes = action.payload.dynamicAttributes;
        draft.extraParams = action.payload.extraParams;
        draft.skuList = generateSKUList(draft.specs, draft.extraParams);
      });

    case 'UPDATE_SKU':
      return { ...state, skuList: action.payload };

    default:
      return state;
  }
}

自定義 Hook 封裝

export function useProductManager() {
  const [state, dispatch] = useReducer(productReducer, initialState);

  const updateBasicInfo = (payload: Partial<ProductState['basicInfo']>) => {
    dispatch({ type: 'UPDATE_BASIC_INFO', payload });
  };

  const updateSpec = (index: number, spec: Partial<ProductState['specs'][0]>) => {
    dispatch({ type: 'UPDATE_SPEC', payload: { index, spec } });
  };

  const setPlatformCategory = async (platformCategoryId: number) => {
    const dynamicAttributes = await fetchDynamicAttributes(platformCategoryId);
    const extraParams = await fetchExtraParams(platformCategoryId);
    dispatch({
      type: 'SET_PLATFORM_CATEGORY',
      payload: { platformCategoryId, dynamicAttributes, extraParams }
    });
  };

  const updateSKU = (skuList: SKU[]) => {
    dispatch({ type: 'UPDATE_SKU', payload: skuList });
  };

  return { state, updateBasicInfo, updateSpec, setPlatformCategory, updateSKU };
}

  • 組件只調(diào)用 updateXXX 或 setPlatformCategory
  • SKU 聯(lián)動邏輯和額外參數(shù)注入都在 reducer 內(nèi)完成
  • 避免在組件里寫大量 useEffect

組件使用示例

const ProductPage = () => {
  const { state, updateBasicInfo, updateSpec, setPlatformCategory, updateSKU } = useProductManager();

  return (
    <div>
      <BasicInfoForm info={state.basicInfo} onChange={updateBasicInfo} />
      <SpecsEditor specs={state.specs} onChange={updateSpec} />
      <SKUList skuList={state.skuList} onChange={updateSKU} />
      <PlatformCategorySelector
        selected={state.basicInfo.platformCategoryId}
        onChange={setPlatformCategory}
      />
    </div>
  );
};

  • 各組件只關(guān)注自己的 slice 數(shù)據(jù)
  • 不用管其他模塊數(shù)據(jù)的聯(lián)動
  • 所有復(fù)雜聯(lián)動邏輯在 hook/reducer 內(nèi)集中處理

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • react之umi配置國際化語言locale的踩坑記錄

    react之umi配置國際化語言locale的踩坑記錄

    這篇文章主要介紹了react之umi配置國際化語言locale的踩坑記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • React中key屬性的警告及解決方案

    React中key屬性的警告及解決方案

    在使用 React 進(jìn)行開發(fā)時,key 屬性是一個至關(guān)重要的概念,尤其在渲染列表時,開發(fā)者在使用 key 屬性時,常常會遇到各種警告信息,本文將詳細(xì)解析這些警告的原因,提供有效的解決方案,并總結(jié)最佳實(shí)踐,需要的朋友可以參考下
    2024-12-12
  • 詳解React中常見的三種路由處理方式選擇

    詳解React中常見的三種路由處理方式選擇

    這篇文章主要為大家詳細(xì)介紹了React中常見的三種路由處理方式該如何選擇,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • React拖拽調(diào)整大小的組件

    React拖拽調(diào)整大小的組件

    這篇文章主要為大家詳細(xì)介紹了React拖拽調(diào)整大小的組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 詳解基于React.js和Node.js的SSR實(shí)現(xiàn)方案

    詳解基于React.js和Node.js的SSR實(shí)現(xiàn)方案

    這篇文章主要介紹了詳解基于React.js和Node.js的SSR實(shí)現(xiàn)方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • React組件的使用詳細(xì)講解

    React組件的使用詳細(xì)講解

    React組件分為函數(shù)組件與class組件;函數(shù)組件是無狀態(tài)組件,class稱為類組件;函數(shù)組件只有props,沒有自己的私有數(shù)據(jù)和生命周期函數(shù);class組件有自己私有數(shù)據(jù)(this.state)和生命周期函數(shù)
    2022-11-11
  • React渲染機(jī)制及相關(guān)優(yōu)化方案

    React渲染機(jī)制及相關(guān)優(yōu)化方案

    這篇文章主要介紹了react中的渲染機(jī)制以及相關(guān)的優(yōu)化方案,內(nèi)容包括react渲染步驟、concurrent機(jī)制以及產(chǎn)生作用的機(jī)會,簡單模擬實(shí)現(xiàn) concurrent mode,基于作業(yè)調(diào)度優(yōu)先級的思路進(jìn)行項(xiàng)目優(yōu)化的兩個hooks,感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07
  • React Native中Mobx的使用方法詳解

    React Native中Mobx的使用方法詳解

    這篇文章主要給大家介紹了關(guān)于React Native中Mobx的使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 一文詳解React渲染優(yōu)化之useImmer

    一文詳解React渲染優(yōu)化之useImmer

    在React日常開發(fā)中,我們常常被重復(fù)渲染或無意義渲染所折磨,窮盡腦汁,做各種優(yōu)化:memo、useMemo、useCallback、immutable等,本文主要講述immutable的簡約版Immer,感興趣的同學(xué)可以一起來學(xué)習(xí)
    2023-05-05
  • 前端使用 React Query 管理“服務(wù)器狀態(tài)”的方法

    前端使用 React Query 管理“服務(wù)器狀態(tài)”的方法

    文章介紹了如何安裝和使用React Query來管理服務(wù)器狀態(tài),文章提供了一個實(shí)戰(zhàn)項(xiàng)目示例,展示了如何使用React Query來實(shí)現(xiàn)獲取、新增、刪除和自動刷新Todo列表等功能,感興趣的朋友跟隨小編一起看看吧
    2025-11-11

最新評論

华安县| 德令哈市| 宾阳县| 垫江县| 河曲县| 富源县| 襄汾县| 炉霍县| 霍邱县| 鱼台县| 文成县| 赤峰市| 邢台县| 林芝县| 南川市| 扎赉特旗| 玉龙| 冀州市| 冀州市| 邢台市| 尼勒克县| 昭觉县| 星座| 儋州市| 呼图壁县| 阿瓦提县| 社旗县| 普安县| 哈巴河县| 雷山县| 陆丰市| 台湾省| 西丰县| 永修县| 梓潼县| 洛扎县| 永仁县| 榆林市| 德钦县| 易门县| 白沙|