Thứ năm, 05/04/2018 | 00:00 GMT+7

Giới thiệu về các khái niệm cốt lõi của Redux


Redux là một containers trạng thái có thể dự đoán được cho các ứng dụng JavaScript và là một công cụ rất có giá trị để tổ chức trạng thái ứng dụng. Đây là một thư viện phổ biến để quản lý trạng thái trong các ứng dụng React, nhưng nó cũng được dùng với Angular, Vue.js hoặc chỉ là JavaScript đơn giản cũ.

Một điều mà hầu hết mọi người cảm thấy khó khăn về Redux là biết khi nào sử dụng nó. Ứng dụng của bạn càng lớn và càng phức tạp thì càng có nhiều khả năng bạn được lợi khi sử dụng Redux. Nếu bạn đang bắt đầu làm việc trên một ứng dụng và bạn dự đoán rằng nó sẽ phát triển đáng kể, bạn có thể bắt đầu với Redux ngay lập tức để khi ứng dụng của bạn thay đổi và mở rộng quy mô, bạn có thể dễ dàng thực hiện những thay đổi đó mà không cần tái cấu trúc rất nhiều mã hiện có của bạn.

Trong phần giới thiệu ngắn gọn về Redux này, ta sẽ đi qua các khái niệm chính: bộ giảm , hành động , người tạo hành độngcửa hàng . Thoạt nhìn nó có vẻ là một chủ đề phức tạp, nhưng các khái niệm cốt lõi thực sự khá đơn giản.

Giảm tốc là gì?

Bộ giảm là một hàm thuần túy lấy trạng thái trước đó và một hành động làm đối số và trả về trạng thái mới. Các hành động là một đối tượng có một loại và một trọng tải tùy chọn:

function myReducer(previousState, action) => {
  // use the action type and payload to create a new state based on
  // the previous state.
  return newState;
}

Các bộ giảm thiểu chỉ định cách trạng thái của ứng dụng thay đổi theo các hành động được gửi đến cửa hàng.

Vì bộ giảm là các hàm thuần túy, ta không thay đổi các đối số được cung cấp cho nó, thực hiện lệnh gọi API, chuyển đổi định tuyến hoặc gọi các hàm không thuần túy như Math.random () hoặc Date.now ().

Nếu ứng dụng của bạn có nhiều phần trạng thái, thì bạn có thể có nhiều bộ giảm bớt. Ví dụ: mỗi tính năng chính bên trong ứng dụng của bạn có thể có bộ giảm tốc riêng. Những người giảm thiểu chỉ quan tâm đến giá trị của trạng thái.

Hành động là gì?

Các hành động là các đối tượng JavaScript đơn giản đại diện cho các khối thông tin gửi dữ liệu từ ứng dụng của bạn đến cửa hàng của bạn. Các hành động có một type và một payload tùy chọn.

Hầu hết các thay đổi trong một ứng dụng sử dụng Redux đều bắt đầu bằng một sự kiện do user kích hoạt trực tiếp hoặc gián tiếp. Các sự kiện như nhấp vào nút, chọn một mục từ menu thả xuống, di chuột vào một phần tử cụ thể hoặc một yêu cầu AJAX vừa trả về một số dữ liệu. Ngay cả việc bốc ban đầu của một trang có thể là một dịp để ta gửi một hành động. Các hành động thường được thực hiện bằng cách sử dụng một trình tạo hành động .

Người tạo hành động là gì?

Trong Redux, trình tạo hành động là một hàm trả về một đối tượng hành động. Người tạo hành động có thể là một bước không cần thiết, nhưng họ giúp mọi thứ trở nên linh hoạt và dễ kiểm tra hơn. Đối tượng hành động được trả về từ trình tạo hành động được gửi đến tất cả các trình giảm bớt khác nhau trong ứng dụng.

Tùy thuộc vào hành động là gì, bộ giảm tốc có thể chọn trả về version mới của phần trạng thái của chúng. Đoạn trạng thái mới được trả về sau đó được đưa vào trạng thái ứng dụng, sau đó được chuyển trở lại ứng dụng React của ta , sau đó khiến tất cả các thành phần của ta hiển thị lại.

Vì vậy, giả sử một user nhấp vào một nút, sau đó ta gọi một trình tạo hành động là một hàm trả về một hành động. Hành động đó có một type mô tả loại hành động vừa được kích hoạt.

Đây là một trình tạo hành động mẫu:

export function addTodo({ task }) {
  return {
    type: 'ADD_TODO',
    payload: {
      task,
      completed: false
    },
  }
}

// example returned value:
// {
//   type: 'ADD_TODO',
//   todo: { task: '🛒 get some milk', completed: false },
// }

Và đây là một trình ADD_TODO đơn giản giải quyết hành động của loại ADD_TODO :

export default function(state = initialState, action) {
  switch (action.type) {
    case 'ADD_TODO':
      const newState = [...state, action.payload];
      return newState;

    // Deal with more cases like 'TOGGLE_TODO', 'DELETE_TODO',...

    default:
      return state;
  }
}

Tất cả các bộ giảm đã xử lý hành động. Các bộ giảm thiểu không quan tâm đến loại hành động cụ thể này chỉ trả lại trạng thái cũ và bộ giảm quan tâm trả lại trạng thái mới. Bây giờ tất cả các thành phần được thông báo về những thay đổi đối với trạng thái. Sau khi được thông báo, tất cả các thành phần sẽ hiển thị với các đạo cụ mới:

{
  currentTask: { task: '🛒 get some milk', completed: false },
  todos: [
    { task: '🛒 get some milk', completed: false },
    { task: '🎷 Practice saxophone', completed: true }
  ],
}

Kết hợp các bộ giảm

Redux cung cấp cho ta một hàm có tên gọi là combineReducers thực hiện hai tác vụ:

  • Nó tạo ra một hàm gọi bộ giảm của ta với phần trạng thái được chọn theo khóa của chúng .
  • Sau đó, nó kết hợp các kết quả vào một đối tượng duy nhất .

Cửa hàng là gì?

Ta tiếp tục đề cập đến store khó nắm bắt nhưng ta vẫn chưa nói về cửa hàng thực sự là gì .

Trong Redux, store đề cập đến đối tượng mang các hành động (đại diện cho những gì đã xảy ra) và bộ giảm (cập nhật trạng thái theo các hành động đó) lại với nhau. Chỉ có một cửa hàng duy nhất trong một ứng dụng Redux.

Cửa hàng có một số nhiệm vụ:

  • Cho phép truy cập vào trạng thái thông qua getState() .
  • Cho phép cập nhật trạng thái qua công dispatch(action) .
  • Giữ toàn bộ trạng thái ứng dụng.
  • Đăng ký người nghe bằng cách sử dụng subscribe(listener) .
  • Hủy đăng ký người nghe thông qua chức năng được trả về bởi subscribe(listener) .

Về cơ bản, tất cả những gì ta cần để tạo một cửa hàng là những bộ giảm giá. Ta mentionned combineReducers để kết hợp nhiều gia giảm thành một. Bây giờ, để tạo một cửa hàng, ta sẽ nhập các đầu combineReducers và chuyển nó vào createStore :

import { createStore } from 'redux';
import todoReducer from './reducers';

const store = createStore(todoReducer);

Sau đó, ta gửi các hành động trong ứng dụng của bạn bằng cách sử dụng phương thức dispatch của cửa hàng như sau:

store.dispatch(addTodo({ task: '📖 Read about Redux'}));
store.dispatch(addTodo({ task: '🤔 Think about meaning of life' }));
// ...

Luồng dữ liệu trong Redux

Một trong những lợi ích của Redux là tất cả dữ liệu trong một ứng dụng đều tuân theo cùng một kiểu vòng đời. Logic của ứng dụng của bạn dễ dự đoán hơn và dễ hiểu hơn vì kiến trúc Redux tuân theo một luồng dữ liệu một chiều nghiêm ngặt .

4 bước chính của vòng đời dữ liệu trong Redux

  • Một sự kiện bên trong ứng dụng của bạn sẽ kích hoạt lệnh gọi đến store.dispatch(actionCreator(payload)) .
  • Cửa hàng Redux gọi trình giảm root với trạng thái hiện tại và hành động.
  • Bộ giảm root kết hợp kết quả của nhiều bộ giảm vào một cây trạng thái duy nhất.
export default const currentTask(state = {}, action){
  // deal with this piece of state
  return newState;
};

export default const todos(state = [], action){
  // deal with this piece of state
  return newState;
};

export default const todoApp = combineReducers({
  todos,
  currentTask,
});

Khi một hành động được phát ra, todoApp sẽ gọi cả hai bộ giảm và kết hợp cả hai bộ kết quả thành một cây trạng thái duy nhất:

return {
  todos: nextTodos,
  currentTask: nextCurrentTask,
};
  • Cửa hàng Redux lưu cây trạng thái hoàn chỉnh được trả về bởi bộ rút gọn root . Cây trạng thái mới hiện là Trạng thái tiếp theo của ứng dụng của bạn.

Kết luận

Đó là rất nhiều điều để nói qua rất ít từ, vì vậy đừng cảm thấy lo sợ nếu bạn vẫn không hoàn toàn chắc chắn về cách tất cả các phần phù hợp với nhau. Redux cung cấp một mô hình rất mạnh mẽ để quản lý trạng thái ứng dụng, vì vậy việc bạn phải thực hành một chút để làm quen với các khái niệm là điều hoàn toàn tự nhiên.

Để tìm hiểu thêm, hãy xem các tài nguyên sau:

🎩 Trong các bài đăng trong tương lai, ta sẽ khám phá các chủ đề nâng cao hơn như xử lý các sự kiện không đồng bộ bằng Redux-Saga hoặc Redux Thunk .


Tags:

Các tin liên quan