使用Redux Toolkit簡化Redux

瞭解Redux Toolkit,這是用於高效Redux開發的通過驗證的工具集。在本文中,你將看到爲何Redux Toolkit值得React社區更多的關注。react

React和Redux被認爲是大規模React應用中管理狀態的最佳組合。然而,隨着時間的推移,Redux的受歡迎程度降低,緣由是:ios

  • 配置Redux Store並不簡單。
  • 咱們須要幾個軟件包來使Redux與React一塊兒工做。
  • Redux須要太多樣板代碼。

帶着這些問題,Redux的建立者Dan Abramov發表了名爲《你可能不須要Redux》的文章,建議人們只在須要的時候使用Redux,而在開發不那麼複雜的應用時,要遵循其餘方法。git

Redux Toolkit解決的問題

Redux Toolkit(以前稱爲Redux Starter Kit)提供了一些選項來配置全局store,並經過儘量地抽象Redux API來更精簡地建立動做和reducers。github

它包括什麼?

Redux Toolkit附帶了一些有用的軟件包,例如Immer,Redux-Thunk和Reselect。它使React開發人員的工做變得更加輕鬆,容許他們直接更改狀態(不處理不可變性),並應用Thunk之類的中間件(處理異步操做)。它還使用了Redux的一個簡單的「選擇器」庫Reselect來簡化reducer函數。redux

ReduxToolkit依賴項

Redux Toolkit API的主要功能?

如下是Redux Took Kit使用的API函數,它是現有Redux API函數的抽象。這些函數並無改變Redux的流程,只是以更易讀和管理的方式簡化了它們。axios

  • configureStore:像從Redux中建立原始的createStore同樣建立一個Redux store實例,但接受一個命名的選項對象並自動設置Redux DevTools擴展。
  • createAction:接受一個Action類型字符串,並返回一個使用該類型的Action建立函數。
  • createReducer:接受初始狀態值和Action類型的查找表到reducer函數,並建立一個處理全部Action類型的reducer。
  • createSlice:接受一個初始狀態和一個帶有reducer名稱和函數的查找表,並自動生成action creator函數、action類型字符串和一個reducer函數。

您能夠使用上述API簡化Redux中的樣板代碼,尤爲是使用createActioncreateReducer方法。然而,這能夠使用createSlice進一步簡化,它能夠自動生成action creator和reducer函數。api

createSlice有什麼特別之處?

它是一個生成存儲片的助手函數。它接受片的名稱、初始狀態和reducer函數來返回reducer、action類型和action creators。框架

首先,讓咱們看看在傳統的React-Redux應用程序中reducers和actions的樣子。異步

Actionsasync

import {GET_USERS,CREATE_USER,DELETE_USER} from "../constant/constants";
export const GetUsers = (data) => (dispatch) => {
 dispatch({
  type: GET_USERS,
  payload: data,
 });
};
export const CreateUser = (data) => (dispatch) => {
 dispatch({
  type: CREATE_USER,
  payload: data,
 });
};
export const DeleteUser = (data) => (dispatch) => {
 dispatch({
  type: DELETE_USER,
  payload: data,
 });
};

Reducers

import {GET_USERS,CREATE_USER,DELETE_USER} from "../constant/constants";
const initialState = {
 errorMessage: "",
 loading: false,
 users:[]
};
const UserReducer = (state = initialState, { payload }) => {
switch (type) {
 case GET_USERS:
  return { ...state, users: payload, loading: false };
case CREATE_USER:
  return { ...state, users: [payload,...state.users],
 loading: false };
case DELETE_USER:
  return { ...state, 
  users: state.users.filter((user) => user.id !== payload.id),
, loading: false };
default:
  return state;
 }
};
export default UserReducer;

如今,讓咱們看看如何使用createSlice簡化並實現相同的功能。

import { createSlice } from '@reduxjs/toolkit';
export const initialState = {
  users: [],
  loading: false,
  error: false,
};
const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    getUser: (state, action) => {
      state.users = action.payload;
      state.loading = true;
      state.error = false;
    },
    createUser: (state, action) => {
      state.users.unshift(action.payload);
      state.loading = false;
    },
    deleteUser: (state, action) => {
      state.users.filter((user) => user.id !== action.payload.id);
      state.loading = false;
    },
  },
});
export const { createUser, deleteUser, getUser } = userSlice.actions;
export default userSlice.reducer;

正如你所看到的,如今全部的動做和reducer都在一個簡單的地方,而在傳統的redux應用中,你須要在reducer中管理每個action和它對應的action,當使用createSlice時,你不須要使用開關來識別action。

當涉及到突變狀態時,一個典型的Redux流程會拋出錯誤,你將須要特殊的JavaScript策略,如spread operator和Object assign來克服它們。因爲Redux Toolkit使用Immer,所以您沒必要擔憂會改變狀態。因爲slice建立了actionsreducers,你能夠導出它們,並在你的組件和Store中使用它們來配置Redux,而無需爲actionsreducers創建單獨的文件和目錄,以下所示。

import { configureStore } from "@reduxjs/toolkit";
import userSlice from "./features/user/userSlice";
export default configureStore({
 reducer: {
  user: userSlice,
 },
});

這個存儲能夠經過使用useSelectoruseDispatch的redux api直接從組件中使用。請注意,您沒必要使用任何常量來標識操做或使用任何類型。

處理異步Redux流

爲了處理異步動做,Redux Toolkit提供了一個特殊的API方法,稱爲createAsyncThunk,它接受一個字符串標識符和一個payload建立者回調,執行實際的異步邏輯,並返回一個Promise,該Promise將根據你返回的Promise處理相關動做的調度,以及你的reducers中能夠處理的action類型。

import axios from "axios";
import { createAsyncThunk } from "@reduxjs/toolkit";
export const GetPosts = createAsyncThunk(
"post/getPosts", async () => await axios.get(`${BASE_URL}/posts`)
);
export const CreatePost = createAsyncThunk(
"post/createPost",async (post) => await axios.post(`${BASE_URL}/post`, post)
);

與傳統的數據流不一樣,由createAsyncThunk處理的action將由分片內的extraReducers部分處理。

import { createSlice } from "@reduxjs/toolkit";
import { GetPosts, CreatePost } from "../../services";
export const initialState = {
  posts: [],
  loading: false,
  error: null,
};
export const postSlice = createSlice({
name: "post",
initialState: initialState,
extraReducers: {
   [GetPosts.fulfilled]: (state, action) => {
     state.posts = action.payload.data;
   },
   [GetPosts.rejected]: (state, action) => {
    state.posts = [];
   },
   [CreatePost.fulfilled]: (state, action) => {
   state.posts.unshift(action.payload.data);
   },
 },
});
export default postSlice.reducer;

請注意,在extraReducers內部,您能夠處理已解決(fulfilled)和已拒絕(rejected)狀態。

經過這些代碼片斷,您能夠看到此工具包在Redux中簡化代碼的效果如何。我建立了一個利用Redux Toolkit的REST示例供您參考。

最後的想法

根據個人經驗,當開始使用Redux時,Redux Toolkit是一個很好的選擇。它簡化了代碼,並經過減小模板代碼來幫助管理Redux狀態。

最後,就像Redux同樣,Redux Toolkit並不是僅爲React構建。咱們能夠將其與其餘任何框架(例如Angular)一塊兒使用。

您能夠經過參考Redux Toolkit的文檔找到更多信息。

謝謝您的閱讀!

相關文章
相關標籤/搜索