首頁 > web前端 > js教程 > 主體

了解 Redux:初學者綜合指南

王林
發布: 2024-08-24 11:06:02
原創
787 人瀏覽過

Understanding Redux: A Beginner

簡介:什麼是 Redux 以及為什麼我們需要它?

隨著 Web 應用程式變得越來越複雜,管理狀態變得越來越具有挑戰性。如果您發現自己陷入了不可預測的狀態變化和難以追蹤的資料流的網路中,那麼您並不孤單。這就是 Redux 發揮救星作用的地方。

Redux 是 JavaScript 應用程式的狀態管理函式庫,以其有效性而聞名,尤其是與 React 一起使用時。透過提供可預測且集中的方式來管理應用程式狀態,Redux 簡化了追蹤資料如何隨時間變化以及應用程式的不同部分如何相互互動的過程。

但是為什麼 Redux 是必要的呢?在任何大型應用程式中,狀態變更都可能發生在多個位置,因此很難找出特定資料在何處以及如何變更。調試和維護此類應用程式可能會成為一場噩夢。 Redux 透過將整個應用程式的狀態儲存在一個稱為儲存的集中位置來解決這些挑戰。這種集中式方法不僅簡化了狀態管理,還增強了應用程式的可預測性和可測試性。

本指南將帶您詳細了解 Redux,從理解其核心概念到在 React 應用程式中設定和使用它。閱讀本文後,您將牢牢掌握 Redux,並有能力將其應用到您的專案中。

Redux 的核心概念

要真正理解 Redux,必須熟悉三個基本概念:store、action 和 reducer。讓我們更深入地了解每個概念。

1. 商店:唯一的真相來源

Redux 的核心是存儲,它是一個集中存儲庫,保存應用程式的整個狀態。商店是應用程式資料的唯一真實來源。無論您的應用程式變得有多大或多複雜,所有狀態都儲存在一個位置,從而更易於管理和調試。

將商店想像成一個巨大的 JavaScript 對象,其中包含應用程式運行所需的所有資訊。無論是使用者資料、UI 狀態或伺服器回應,所有內容都儲存在該物件中。這種集中式方法與在各個元件內本地管理狀態的傳統方法形成鮮明對比,這可能會導致追蹤狀態變更的不一致和困難。

Redux 中的儲存空間是不可變的,這意味著一旦設定了狀態,就無法直接變更。相反,只要需要更改,就會建立一個新狀態。這種不變性對於維持應用程式的可預測性至關重要,因為它確保每個狀態變更都是有意且可追蹤的。

2. 行動:描述發生了什麼

Redux 中的操作是描述應用程式中的事件或更改的純 JavaScript 物件。它們就像傳遞有關應用程式中發生的情況的訊息的信使。每個操作都有一個定義操作性質的類型屬性,以及一個可選的有效負載屬性,其中包含與該操作相關的任何其他資料。

例如,在待辦事項清單應用程式中,操作可能表示新增新的待辦事項、完成現有項目或刪除項目。每個操作都有一個唯一的類型,例如 ADD_TODO、TOGGLE_TODO 或 DELETE_TODO,並且可能包含其他數據,例如待辦事項的 ID 或文字。

操作被分派到存儲,並由減速器處理(我們將在接下來討論)。透過清楚定義應用程式中發生的情況,操作有助於保持清晰且易於理解的資料變更流。

3.Reducers:定義狀態如何改變

Reducers 是 Redux 中的純函數,定義應用程式的狀態應如何回應操作而改變。它們以當前狀態和操作作為參數並傳回一個新狀態。術語「純函數」意味著reducer的輸出僅取決於其輸入(當前狀態和操作),並且不會產生任何副作用,例如修改外部變數或執行非同步操作。

在 Redux 中,reducers 負責實際的狀態更新。當分派一個操作時,Redux 將目前狀態和操作傳遞給適當的減速器,然後計算並傳回新狀態。這個過程確保狀態以可預測和可追蹤的方式發生變化。

例如,待辦事項清單應用程式的減速器可能如下所示:

function todoReducer(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, action.payload];
    case 'TOGGLE_TODO':
      return state.map(todo =>
        todo.id === action.payload.id
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    default:
      return state;
  }
}

登入後複製

在此範例中,todoReducer 處理兩種類型的操作:ADD_TODO 和 TOGGLE_TODO。根據操作類型,它可以為狀態新增新的待辦事項或切換現有專案的已完成狀態。減速器總是傳回一個新的狀態對象,確保原始狀態保持不變。

設定和使用 Redux:詳細​​的逐步指南

現在我們已經介紹了 Redux 的核心概念,是時候看看它們如何在實際應用程式中結合在一起了。在本節中,我們將逐步介紹在簡單的 React 應用程式中設定和使用 Redux 的過程。

步驟1:安裝Redux及相關套件

使用 Redux 的第一步是安裝必要的軟體包。 Redux 本身是一個獨立的函式庫,但與 React 一起使用時,您還需要安裝react-redux,這是一個提供將 Redux 與 React 元件整合的綁定的套件。

要安裝 Redux 和 React-Redux,請開啟終端機並在專案目錄中執行以下命令:

npm install redux react-redux
登入後複製

此指令會安裝 redux 和 react-redux,我們將使用它們將 React 元件連接到 Redux 儲存。

第 2 步:建立商店

安裝 Redux 後,下一步就是建立儲存。儲存保存應用程式的狀態並提供用於調度操作和訂閱狀態變更的方法。

在此範例中,我們將為簡單的待辦事項清單應用程式建立一個商店。首先建立一個處理狀態變更的減速器函數:

import { createStore } from 'redux';

// This is our reducer function
function todoReducer(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, action.payload];
    case 'TOGGLE_TODO':
      return state.map(todo =>
        todo.id === action.payload.id
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    default:
      return state;
  }
}

// Create the store
const store = createStore(todoReducer);
登入後複製

在此程式碼中,todoReducer 函數處理兩種類型的操作:ADD_TODO 用於新增新的待辦事項,TOGGLE_TODO 用於切換專案的完成狀態。 Redux 中的 createStore 函數用於建立存儲,並傳入 todoReducer 作為參數。

第 3 步:定義操作和操作創建者

動作在 Redux 中至關重要,因為它們描述了應用程式中發生的事情。但是,每次想要分派操作時手動建立操作物件可能會變得很麻煩。這就是動作創建者發揮作用的地方。動作創建者是傳回動作物件的函數。

讓我們定義一個動作建立器來新增待辦事項:

function addTodo(text) {
  return {
    type: 'ADD_TODO',
    payload: { id: Date.now(), text, completed: false }
  };
}
登入後複製

addTodo 函數接受一個文字參數並傳回一個類型為 ADD_TODO 的操作物件和包含待辦事項資料的有效負載。這個動作創建器簡化了分派動作的過程,使程式碼更具可讀性和可維護性。

您也可以定義其他操作建立者,例如toggleTodo,用於切換待辦事項的完成狀態:

function toggleTodo(id) {
  return {
    type: 'TOGGLE_TODO',
    payload: { id }
  };
}
登入後複製

第 4 步:調度操作以更新狀態

儲存和操作就位後,您現在可以調度操作來更新狀態。分派一個動作是你通知 Redux 應用程式中發生了一些事情,觸發適當的減速器來更新狀態的方式。

以下是如何排程操作來新增和切換待辦事項:

store.dispatch(addTodo('Learn Redux'));
store.dispatch(addTodo('Build an app'));
store.dispatch(toggleTodo(1621234567890));
登入後複製

當您分派 addTodo 操作時,Redux 會使用目前狀態和操作呼叫 todoReducer,reducer 將傳回一個包含新增的待辦事項的新狀態。同樣,當您調度toggleTodo操作時,reducer會更新指定待辦事項的完成狀態。

第 5 步:訪問並訂閱狀態更改

要讀取應用程式的目前狀態,可以使用商店提供的 getState 方法。此方法傳回儲存在 Redux 儲存中的整個狀態物件:

console.log(store.getState());
// Output: [{ id: 1621234567890, text: 'Learn Redux', completed: true }, 
//          { id: 1621234567891, text: 'Build an app', completed: false }]
登入後複製

除了讀取狀態之外,還可以使用 subscribe 方法訂閱狀態變化。此方法可讓您在狀態變更時執行回呼函數,這對於更新 UI 或執行其他副作用以回應狀態更新非常有用:

const unsubscribe = store.subscribe(() => {
  console.log('State updated:', store.getState());
});
登入後複製

訂閱完狀態變更後,可以透過呼叫 subscribe 傳回的函數來取消訂閱:

unsubscribe();
登入後複製

步驟 6:將 Redux 連接到 React 元件

要將 Redux 與 React 集成,您需要將 React 元件連接到 Redux 儲存。這就是react-redux套件發揮作用的地方,它提供了Provider、useSelector和useDispatch實用程式。

首先將整個應用程式包裝在 Provider 元件中,並將 Redux 儲存作為 prop 傳遞。這使得 Redux 儲存可用於 React 應用程式中的所有元件:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import App from './App';
import todoReducer from './reducers';

// Create the Redux store
const store = createStore(todoReducer);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
登入後複製

接下來,使用 useSelector 和 useDispatch 掛鉤將您的元件連接到 Redux 儲存。 useSelector 允許您存取狀態,而 useDispatch 允許您分派操作:

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { addTodo, toggleTodo } from './actions';

function TodoList() {
  const todos = useSelector(state => state);
  const dispatch = useDispatch();

  const handleAddTodo = (text) => {
    dispatch(addTodo(text));
  };

  const handleToggleTodo = (id) => {
    dispatch(toggleTodo(id));
  };

  return (
    <div>
      <button onClick={() => handleAddTodo('New Todo')}>Add Todo</button>
      <ul>
        {todos.map(todo => (
          <li
            key={todo.id}
            onClick={() => handleToggleTodo(todo.id)}
            style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
          >
            {todo.text}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoList;
登入後複製

In this example, the TodoList component displays a list of todo items, with the ability to add new items and toggle their completion status. The useSelector hook retrieves the state from the Redux store, while the useDispatch hook allows the component to dispatch actions.

By connecting your React components to Redux in this way, you can ensure that your application's state is managed consistently and predictably.

Best Practices and Common Pitfalls

While Redux is a powerful tool for managing state in complex applications, it also comes with its own set of best practices and potential pitfalls. Understanding these will help you avoid common mistakes and make the most of Redux in your projects.

Best Practices

  • Keep Your State Normalized: In large applications, it's essential to keep your state normalized, meaning that you avoid nesting data too deeply. Instead of storing entire objects within other objects, store only the references (e.g., IDs) and keep the actual objects in a separate, flat structure. This approach simplifies state updates and prevents unnecessary data duplication.
  • Use Action Creators: Action creators are functions that return action objects. They not only make your code more readable but also allow you to modify the structure of actions later without changing the code that dispatches them. Always use action creators instead of directly creating action objects in your components.
  • Use Immutable Update Patterns: Redux relies on immutability, meaning that state objects should never be modified directly. Instead, always return new objects when updating the state in reducers. You can use tools like the spread operator (...) or utility libraries like Immutable.js or Immer to help with this.
  • Keep Reducers Pure: Reducers should be pure functions, meaning that they should only depend on their arguments and not produce side effects, such as modifying external variables or making API calls. This purity ensures that your state changes are predictable and easy to test.
  • Split Your Reducers: As your application grows, so will your state. Instead of having one large reducer that handles everything, split your reducers into smaller, more manageable functions, each responsible for a specific part of the state. Redux provides a combineReducers function to help you merge these smaller reducers into a single root reducer.
  • Use Middleware for Side Effects: Redux is designed to be a synchronous state container, but many applications need to handle asynchronous actions, such as API calls. To manage these side effects, use middleware like redux-thunk or redux-saga, which allows you to handle asynchronous actions in a clean and maintainable way.

Common Pitfalls to Avoid

  • Overusing Redux: Not every piece of state needs to be stored in Redux. While Redux is great for managing application-wide state, it's overkill for local UI state that doesn't need to be shared across components. For example, the state of a dropdown menu or a modal window is better managed with React's built-in useState hook.
  • Mutating State Directly: One of the most common mistakes in Redux is directly mutating the state object in reducers. Doing so can lead to subtle bugs and make your application unpredictable. Always return a new state object instead of modifying the existing one.
  • Putting Everything in One Reducer: While it's possible to manage your entire application's state with a single reducer, doing so will quickly become unmanageable as your application grows. Instead, break down your state into smaller pieces and create a reducer for each piece. Use combineReducers to merge them into a single root reducer.
  • Ignoring the Redux DevTools: Redux DevTools is an invaluable tool for debugging and understanding how your state changes over time. It allows you to inspect every action that is dispatched, view the current state, and even "time travel" by replaying actions. Make sure to integrate Redux DevTools into your development environment.
  • Not Handling Side Effects Properly: Redux is designed to be a synchronous state container, but most applications need to deal with asynchronous actions, such as API calls. If you handle these side effects within reducers or actions, you break the purity of your functions and make your code harder to test and maintain. Instead, use middleware like redux-thunk or redux-saga to manage side effects.

Conclusion and Next Steps

In this comprehensive guide, we've covered the fundamentals of Redux, from its core concepts to setting up and using it in a simple React application. Redux is a powerful tool for managing state in complex applications, but it also comes with its own learning curve and best practices.

透過了解儲存、操作和化簡器,您可以控制應用程式的狀態並確保其行為可預測且一致。透過提供的逐步指南,您現在應該能夠在自己的專案中設定 Redux 並開始像專業人士一樣管理狀態。

但是,Redux 是一個廣闊的主題,具有許多高級功能和用例。為了加深您的理解,請考慮探索以下內容:

  • 中間件:學習如何使用 redux-thunk 和 redux-saga 等中間件處理非同步操作和副作用。
  • Redux Toolkit:使用 Redux Toolkit 簡化 Redux 開發,Redux Toolkit 是一組工具和最佳實踐,讓 Redux 的使用更加輕鬆、高效。
  • 測試 Redux 應用程式:探索如何為您的減速器、操作和連接的組件編寫單元測試。
  • 進階模式:發現進階 Redux 模式,例如處理複雜的狀態形狀、最佳化效能以及將 Redux 與其他程式庫整合。
  • 社區和資源:加入 Redux 社區,閱讀官方文檔,探索線上教學和課程以繼續學習。

請記住,掌握 Redux 需要時間和練習。你使用它的次數越多,你就會變得越舒服。不斷嘗試,不斷學習。

以上是了解 Redux:初學者綜合指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!