ReactJS - 使用 useReducer

你好,有抱负的程序员們!今天,我們將踏上一段令人興奮的旅程,進入React hooks的世界,特別聚焦於強大的useReducer hook。如果你是編程新手,別擔心——我會一步一步地指導你,就像我過去教過無數學生那樣。讓我們一起來探索吧!

ReactJS - Using useReducer

useReducer是什麼?

在我們深入細節之前,讓我們先來了解useReducer到底是什麼。想像一下你正在玩一款電子遊戲,你的角色有不同的狀態——健康、力量和速度。當你玩遊戲時,這些狀態會根據你的行動而改變。useReducer就像遊戲引擎一樣,根據特定的規則管理這些狀態的變化。

在React術語中,useReducer是一個hook,它幫助我們在應用程序中管理複雜的狀態邏輯。當你的狀態中有多個子值,或者當下一個狀態依賴於前一个狀態時,它特別有用。

useReducer hook的簽名

現在,讓我們看看如何在代碼中實際使用useReducer。這是它基本的結構:

const [state, dispatch] = useReducer(reducer, initialState);

讓我們分解這個結構:

  • state:這是我們當前的狀態,就像遊戲比喻中角色的當前健康狀態。
  • dispatch:這是一個函數,我們用它來發送更新我們狀態的行動。
  • reducer:這是一個函數,它指定了我們的狀態應該如何響應行動而變化。
  • initialState:這是我們應用程序的初始狀態。

現在這可能看起來有點混亂,但別擔心!我們馬上就會看到它在實際操作中的情況,然後一切就會豁然開朗。

使用reducer hook

讓我們創建一個簡單的計數器應用程序來了解useReducer是如何工作的。我們將從基本設置開始,然後逐步建立。

import React, { useReducer } from 'react';

// 步驟1:定義初始狀態
const initialState = { count: 0 };

// 步驟2:創建reducer函數
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}

// 步驟3:創建Counter組件
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);

return (
<div>
計數:{state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}

export default Counter;

讓我們一步一步分解這個過程:

  1. 我們從React中導入useReducer
  2. 我們定義我們的initialState,計數為0。
  3. 我們創建一個reducer函數,它接受當前的state和一個action,並根據行動類型返回新的狀態。
  4. 在我們的Counter組件中,我們使用useReducer來獲取我們當前的statedispatch函數。
  5. 我們渲染當前的計數和兩個按鈕,當點擊時會分發'increment'和'decrement'行動。

當你點擊'+'按鈕時,它會分發一個'increment'行動,我們的reducer會處理這個行動並增加計數。'-'按鈕的工作原理與減少計數相似。

使用useReducer

現在,我們已經看到了一個基本示例,讓我們探討一個更複雜的情景。想像一下我們正在構建一個簡單的任務管理應用程序。我們將使用useReducer來處理添加和刪除任務。

import React, { useReducer, useState } from 'react';

// 步驟1:定義初始狀態
const initialState = { tasks: [] };

// 步驟2:創建reducer函數
function reducer(state, action) {
switch (action.type) {
case 'ADD_TASK':
return { tasks: [...state.tasks, action.payload] };
case 'REMOVE_TASK':
return { tasks: state.tasks.filter((task, index) => index !== action.payload) };
default:
return state;
}
}

// 步驟3:創建TaskManager組件
function TaskManager() {
const [state, dispatch] = useReducer(reducer, initialState);
const [newTask, setNewTask] = useState('');

const handleAddTask = () => {
if (newTask.trim()) {
dispatch({ type: 'ADD_TASK', payload: newTask });
setNewTask('');
}
};

const handleRemoveTask = (index) => {
dispatch({ type: 'REMOVE_TASK', payload: index });
};

return (
<div>
<input
value={newTask}
onChange={(e) => setNewTask(e.target.value)}
placeholder="輸入一個新任務"
/>
<button onClick={handleAddTask}>添加任務</button>
<ul>
{state.tasks.map((task, index) => (
<li key={index}>
{task}
<button onClick={() => handleRemoveTask(index)}>刪除</button>
</li>
))}
</ul>
</div>
);
}

export default TaskManager;

在這個更複雜的例子中:

  1. 我們的initialState現在有一個任務數組。
  2. reducer函數處理兩種類型的行動:'ADD_TASK'和'REMOVE_TASK'。
  3. TaskManager組件中,我們使用useReducer來管理任務,並使用useState來處理輸入字段。
  4. 我們有處理添加和刪除任務的函數,它們分發適當的行動。
  5. 我們渲染一個用於新任務的輸入字段、一個添加任務的按鈕和一個顯示現有任務及刪除按鈕的列表。

這個例子展示了useReducer如何能夠幫助我們以清晰和有組織的方式管理更複雜的狀態邏輯。

方法總結

這裡是一個總結我們所涵蓋的關鍵方法和概念的表格:

方法/概念 描述 示例
useReducer 一個用於管理複雜狀態邏輯的React hook const [state, dispatch] = useReducer(reducer, initialState);
reducer 一個指定狀態如何響應行動而變化的函數 function reducer(state, action) { ... }
dispatch 一個用於發送更新狀態行動的函數 dispatch({ type: 'ADD_TASK', payload: newTask })
行動 一個描述應對狀態進行何種變化的對象 { type: 'INCREMENT' }
初始狀態 應用程序的起始狀態 const initialState = { count: 0 };

記住,有效地學習使用useReducer需要練習。如果它立即沒有引起你的共鳴,不要氣餒——甚至有經驗的開發者有时也需要時間來理解新概念。持續編程,持續嘗試,最重要的是,享受樂趣!在你意識到之前,你將會像專家一樣管理複雜的狀態。快樂編程!

Credits: Image by storyset