useReducer + useContext vs Redux ![image](https://hackmd.io/_uploads/HynFSf7Nkx.png) --- ###### tags: `Redux`, `React`, `基本知識` <br> ## 前提 在學習程式裡,通常讀懂了功能,記住了各別使用的方式,卻不知道要用在哪裡,使用的時機點是什麼時候。 這些都是經驗累積,或者由經驗者帶著操作和分享才順利學習到的。 至於這次分享是我在一次的面試線下作業裡用到,也花了點時間去整理(怪不得我在寫得時候覺得還蠻熟悉的),然後這文章就誕生了。 ## useContext + useReducer ![image](https://hackmd.io/_uploads/SkSznfX4Jl.png) ### 什麼是 useContext? - useContext 是 React的一個 Hook ,用於跨層級共享狀態或數據用的。它的主要作用是避免過多的 props 傳遞(Prop Drilling) 1. Context 物件: - 用來保存可以被多個物件共享的數據。 - 透過 Provider 和 Consumer 實現數據的傳遞與使用。 2. 跨層級共享數據: - 父組件可以通過 Provider 提供數據,子組件通過 useContext 獲取。 ``` const value = useContext(MyContext); ``` - 這應該是在人生第一次嘗試跨多層傳遞資訊的時候,最常會用的 hook,API拿到了就丟進去,然後在某個Component 或者 page再抓出來。 當然現在上線的某些輕量級專業也會用的到。 ### 什麼是 useReducer? - useReducer 也是 React 的一個 Hook,用於處理複雜和統整煩瑣的功能,它特別適合用於多層次的狀態更新,或者當多個行為(actions) 會影響同一狀態時。 1. Reducer函數: - 用一個純函數,負責根據當前的狀態和觸發的action,返回新的狀態。 - 簡化多個 setState 操作,將所有邏輯集中管理。 2. 狀態與派發: - state: 當前的狀態 - dispatch:一個函數,用來傳遞 action, 觸發狀態更新,可以想像為 移動版的 setState。 ``` const [state, dispatch] = useReducer(reducer, initialState); // reducer 就是 所有的action // initialState 就是 初始值。 ``` ![image](https://hackmd.io/_uploads/SJntymm4kl.png) ### 一起使用的 例子: 1. 建立 Context 和 Reducer ``` import React, { createContext, useReducer, useContext } from 'react'; const AppContext = createContext(); const initialState = { count: 0 }; const reducer = (state, action) => { switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } }; ``` 2. 創建 Provider 組件 ``` export const AppProvider = ({ children }) => { const [state, dispatch] = useReducer(reducer, initialState); return ( <AppContext.Provider value={{ state, dispatch }}> {children} </AppContext.Provider> ); }; ``` 3. 消費數據 ``` const Counter = () => { const { state, dispatch } = useContext(AppContext); return ( <div> <p>Count: {state.count}</p> <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button> <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button> </div> ); }; ``` 4. 回到 app.jsx: ``` const App = () => ( <AppProvider> <Counter /> </AppProvider> ); export default App; ``` ### 適用場景的選擇: - 只需要共享數據:使用 useContext - 如:主題切換、用戶數據。 - 需要處理複雜的邏輯:使用 useReducer - 如:表單、多步操作的狀態管理。 - 需要跨組件共享且有複雜邏輯:結合 useReducer 和 useContext - 如:全局的應用狀態(類似 Redux 功能)。 --- ## Redux: 經過上面的 useReducer 和 useContext的介紹,是否覺得跟Redux似曾相識? ![image](https://hackmd.io/_uploads/Byzt_QmEke.png) redux 是一個套件,提到 middleware ,大家應該會優先想到 Redux,zustand 吧?比起 useReducer 和 useContext,Redux看起來能做的事情更多,例如 query 也可以。 對於Redux來說,它具備了 useContext 和 useReducer 的功能,但在便利下,也需要做很多前置設定。 ![image](https://hackmd.io/_uploads/r1jpqXmVke.png) ### 適用場景: ![image](https://hackmd.io/_uploads/r1M1sXQ41l.png) ## 總結: useReducer 和 useContext 是React 內部元件,不需要安裝就可以直接,可以它們的全局管理和傳遞資料是有限的。適合處理簡單的邏輯和較小的專案。 Redux 適合大型應用的全局狀態管理,功能強大,可擴展性高,尤其適用於需要中間件或全局狀態的場景,還有很多很多的tools可以擴充其功能。 希望這篇文章可以幫助大家在未來專案選擇裡,做出最好的決定。 願這文章有幫助你學習!我們下篇文章再見! PEACE! ![image alt](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYXg4Znc1MDNtYnZydXE0aDNxNmh0dnhscjU3YzhpcmJjaHVwMjJjaiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/fxe8v45NNXFd4jdaNI/giphy.gif)