iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0
Modern Web

你 React 了嗎? 30 天解鎖 React 技能系列 第 27

[DAY 27] Redux Toolkit 管理組件的共用資料

  • 分享至 

  • xImage
  •  

cover

安裝環境

創建模板 React + Redux Toolkit

npx create-react-app my-app --template redux

安裝 react-redux、@reduxjs/toolkit

// npm 
npm i react-redux @reduxjs/toolkit

// yarn
yarn add react-redux @reduxjs/toolkit

可依自己的需求安裝環境


認識變數

使用 Redux Toolkit,你會聽到幾個關鍵字:

  • store:用來存放資料狀態
  • reducer:用來放改變 state 狀態的方法
  • action:reducer 要修改 state 的話,需要傳入 action ,去判斷要啟動哪個 reducer,藉由 dispatch 呼叫方法
  • Provider:在所有組件的最外面包一層 Provider,傳入 store,所有被包覆的組件都可以使用到 store 的狀態。
  • slice:存放 state、reducer、action 的檔案

Redux 流程

  1. 創建 Store
  2. 在最外層加入 Provider,並傳入 store,使整個組件都能使用 store 資料
  3. 創建 Slice,設定 state、reducer、action
  4. 畫面渲染,取得 state、dispatch 方法改變狀態

範例:todoList

製作一個 todoList 列表,輸入框輸入文字,點擊按鈕後新增行程


創建 store

store/index.js

import { configureStore } from "@reduxjs/toolkit";
import todoReducer from "./slice/todo";

export default configureStore({
  reducer: {
    todo: todoReducer,
  },
});

將 slice 新增在 reducer

configureStore:創建 store 的參數,原生為 creactStore,使用 creactStore 時會有被棄用的警告


import { configureStore } from "@reduxjs/toolkit";
import todoReducer from "./slice/todo";
import productReducer from "./slice/product";

export default configureStore({
  reducer: {
    todo: todoReducer,
    product: productReducer
  },
});

如有多個檔案,一樣 import 進來,新增在 reducer


在最外層加入 Provider

src/App.js

import { Provider } from "react-redux";
import store from "./store/index";
import Todo from "./Todo";

export default function App() {
  return (
    <Provider store={store}>
      <Todo />
    </Provider>
  );
}

載入 Providerstore,Provider 組件傳入 store
包在 Provider 裡的組件都可以使用 store


創建 Slice

store/slice/todo.js

import { createSlice } from "@reduxjs/toolkit";

export const todoSlice = createSlice({
  name: "todo",

  initialState: {
    todolist: [
      { id: 1, name: "起床" },
      { id: 2, name: "刷牙洗臉" },
      { id: 3, name: "吃早餐" },
      { id: 4, name: "上班" }
    ]
  },

  reducers: {
    addTodo: (state, action) => {
      state.todolist.push(action.payload);
    }
  }
});

export const { addTodo } = todoSlice.actions; // 取用方法
export const selectTodo = (state) => state.todo; // 取用資料
export default todoSlice.reducer;

createSlice:創建 slice,把 Redux 原生的 state、reducer、action 都合在一包,稱之為 slice

name:取一個相關的名稱

initialState:所有狀態的初始值

reducers:存放函式,傳入兩個參數,第一個為需要修改的 state,第二個為 action 讓你傳入的參數,用來改變 state


畫面渲染

components/TodoList.js

import { useSelector } from "react-redux";
import { selectTodo } from "../store/slice/todo";

const TodoList = () => {
  const states = useSelector(selectTodo);

  return (
    <ul>
      {states.todolist.map((i) => (
        <li key={i.id}>{i.name}</li>
      ))}
    </ul>
  );
};

export default TodoList;

將預設行程渲染出來

useSelector:拿取 store 的 state,傳入在 slice 建立的 selectTodo

src/Todo.js

import { useDispatch } from "react-redux";
import TodoList from "./components/TodoList";
import { addTodo } from "./store/slice/todo";
import { useState } from "react";

export default function Todo() {
  const [text, setText] = useState("");

  const changeText = (e) => {
    setText(e.target.value);
  };

  const dispatch = useDispatch();

  const handleAddTodo = () => {
    dispatch(addTodo({ id: new Date().getTime(), name: text }));
  };

  return (
    <div>
      <input
        type="text"
        value={text}
        onChange={changeText}
      />

      <TodoList />

      <button onClick={handleAddTodo}>
        新增行程
      </button>
    </div>
  );
}

建立輸入框,按鈕新增行程,將 id、輸入文字傳入 addTodo

useDispatch:需藉由 useDispatch 使用 store 裡的 actions,傳入在 slice 建立的 addTodo()

todoList

打開 codesandbox 程式碼範例 一起玩看看吧!


結語

Redux Toolkit 真的比 Redux 好懂很多,真是感謝 Redux Toolkit 的出現/images/emoticon/emoticon42.gif
如果專案滿大的話,滿推薦使用 Redux Toolkit 來管理狀態資料,
學會了基本的 store 使用,明天繼續來講怎麼用 Redux Toolkit 操作非同步吧!


本文將同步更新至我的部落格
Lala 的前端大補帖



上一篇
[DAY 26] Redux 原理與 Redux Toolkit
下一篇
[DAY 28] Redux Toolkit 非同步操作createAsyncThunk
系列文
你 React 了嗎? 30 天解鎖 React 技能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言