在 React 項目中使用 Redux 實現公共下拉選狀態共享并通知各組件更新的完整方案如下:
1. 安裝 Redux 必要依賴
npm install @reduxjs/toolkit react-redux
2. 創建 Redux Store 和 Slice
store/selectSlice.js
import { createSlice } from '@reduxjs/toolkit';const initialState = {value: 'default', // 默認值options: [{ value: 'opt1', label: 'Option 1' },{ value: 'opt2', label: 'Option 2' }]
};export const selectSlice = createSlice({name: 'select',initialState,reducers: {setSelectValue: (state, action) => {state.value = action.payload;},updateOptions: (state, action) => {state.options = action.payload;}}
});export const { setSelectValue, updateOptions } = selectSlice.actions;
export default selectSlice.reducer;
store/store.js
import { configureStore } from '@reduxjs/toolkit';
import selectReducer from './selectSlice';export const store = configureStore({reducer: {select: selectReducer}
});
3. 在應用頂層提供 Store
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './store/store';
import App from './App';ReactDOM.render(<Provider store={store}><App /></Provider>,document.getElementById('root')
);
4. 創建公共下拉選組件
components/GlobalSelect.js
import { Select } from 'antd';
import { useDispatch, useSelector } from 'react-redux';
import { setSelectValue } from '../store/selectSlice';const GlobalSelect = () => {const dispatch = useDispatch();const { value, options } = useSelector((state) => state.select);return (<Selectvalue={value}onChange={(val) => dispatch(setSelectValue(val))}options={options}style={{ width: 200 }}/>);
};export default GlobalSelect;
5. 在任意子組件中響應狀態變化
components/DisplayComponent.js
import { useEffect } from 'react';
import { useSelector } from 'react-redux';const DisplayComponent = () => {const selectValue = useSelector((state) => state.select.value);useEffect(() => {console.log('下拉選值變化:', selectValue);// 這里可以執行數據獲取等副作用操作}, [selectValue]);return <div>當前選擇: {selectValue}</div>;
};export default DisplayComponent;
6. 在頁面中使用(完整示例)
App.js
import GlobalSelect from './components/GlobalSelect';
import DisplayComponent from './components/DisplayComponent';
import AnotherComponent from './components/AnotherComponent';function App() {return (<div style={{ padding: 20 }}><h2>公共區域下拉選</h2><GlobalSelect /><div style={{ marginTop: 50 }}><h3>組件1</h3><DisplayComponent /></div><div style={{ marginTop: 50 }}><h3>組件2</h3><AnotherComponent /></div></div>);
}export default App;
7. 異步數據加載示例(如需要)
// 在需要的地方dispatch異步action
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { updateOptions } from '../store/selectSlice';const DataLoader = () => {const dispatch = useDispatch();useEffect(() => {const fetchOptions = async () => {const res = await fetch('/api/options');const options = await res.json();dispatch(updateOptions(options));};fetchOptions();}, [dispatch]);return null;
};
關鍵實現原理說明:
- 狀態集中管理:所有下拉選相關狀態存儲在 Redux store 中
- 單向數據流:
- 下拉選變更 → dispatch action → store 更新 → 所有訂閱組件自動更新
- 組件通信:
- 任何組件都可以通過
useSelector
獲取最新值 - 任何組件都可以通過
useDispatch
修改值
- 任何組件都可以通過
性能優化建議:
-
精細化訂閱:組件只訂閱需要的具體值
// 只訂閱value變化(options變化不會觸發重渲染) const value = useSelector((state) => state.select.value);
-
使用memo:對子組件進行記憶化
import { memo } from 'react'; const MemoizedComponent = memo(DisplayComponent);
-
批量更新:多個狀態變更使用
redux-batched-actions
替代方案對比(Redux vs Context)
特性 | Redux | Context API |
---|---|---|
適用場景 | 中大型應用 | 小型應用 |
調試工具 | 強大的Redux DevTools | 無內置工具 |
性能 | 自動淺比較優化 | 需要手動優化 |
學習曲線 | 較高 | 較低 |
異步處理 | 內置Thunk/Saga支持 | 需自行實現 |
對于需要全局共享且頻繁更新的狀態(如公共下拉選),Redux 仍然是更專業的選擇。