iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0

Redux-thunk

Redux 本身處理同步狀態管理,即每個 action 都會立即被 reducer 處理。然而,現實中我們經常需要處理異步操作,比如從伺服器獲取數據或提交表單。為了讓 Redux 支持異步操作,就會採用方法之一的redux-thunk。

@reduxjs/toolkit本身就帶有redux-thunk,如果是用一般的redux就會需要再去額外安裝

dataSlice.js

會延用之前的架構喔,dataSlice.js放在modules

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

const dataSlice = createSlice({
    name: "data",
    initialState: {
        data: [],
        loading: false,
        error: null,
    },
    reducers: {
        fetchDataStart: (state) => {
            state.loading = true;
        },
        fetchDataSuccess: (state, action) => {
            state.loading = false;
            state.data = action.payload;
        },
        fetchDataFailure: (state, action) => {
            state.loading = false;
            state.error = action.payload;
        },
    },
});

export const { fetchDataStart, fetchDataSuccess, fetchDataFailure } = dataSlice.actions;

export default dataSlice.reducer;

// 這是我們的異步 thunk
export const fetchData = () => async (dispatch) => {
    try {
        dispatch(fetchDataStart());
        const response = await axios.get("https://jsonplaceholder.typicode.com/posts");
        dispatch(fetchDataSuccess(response.data));
    } catch (error) {
        dispatch(fetchDataFailure(error.message));
    }
};

npm install axiosaxios api需要自行在安裝

  • createSlice:用於簡化定義 reducers 和 actions 的過程,這裡定義了 dataSlice,包含初始狀態和幾個 reducer 函數。

  • initialState:這裡定義了三個狀態值:
    data: 用於存儲從 API 獲取的數據。
    loading: 用於跟蹤數據加載過程中是否還在進行中。
    error: 用於存儲異常錯誤信息。

  • 同步 reducer 函數:
    fetchDataStart: 請求開始時,將 loading 設置為 true。
    fetchDataSuccess: 請求成功後,將 loading 設置為 false,並將獲取的數據存儲到 state.data。
    fetchDataFailure: 請求失敗時,將 loading 設置為 false,並將錯誤信息存儲到 state.error。

  • 異步 thunk 函數:
    fetchData: 異步請求函數,用 async/await 發送 API 請求,根據結果調用不同的 reducer 更新狀態。

  • dispatch 的作用是用來發送(dispatch)一個 action 到 Redux store,從而觸發對應的 reducer 函數來更新應用中的狀態。

index.js

這邊指的是store裡的,外面的統一用main.js好了

import { configureStore } from "@reduxjs/toolkit";
import dataReducer from "./modules/dataSlice";
const store = configureStore({
    reducer: {
        data: dataReducer,
    },
});

export default store;

同之前的配置並無甚麼特殊變化,不過其實他有多一個回調函數middleware,因為 @reduxjs/toolkit 已經自動配置了 redux-thunk。只有在需要添加或自定義其他中間件時,才需要顯式寫 middleware。

app.js

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchData } from './store/modules/dataSlice';

const DataComponent = () => {
  const dispatch = useDispatch();
  const { data, loading, error } = useSelector((state) => state.data);

  useEffect(() => {
    dispatch(fetchData());  // 組件加載時發送請求
  }, [dispatch]);

  if (loading) {
    return <p>Loading...</p>;
  }

  if (error) {
    return <p>Error: {error}</p>;
  }

  return (
    <div>
      <h1>Data from API</h1>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default DataComponent;

執行 dispatch(fetchData()) 時,它表示你想要發送 fetchData 這個異步函數(thunk)作為 action。

main.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')).render(
  <Provider store={store}>
    <App />
  </Provider>
);

這沒什麼變動就不多做說明了

今天就這樣囉,異步操作主要還是api之類的會很需要,再來redux本身是專門處理同步的如果沒有react-thunk就無法使用。


上一篇
[day20]Redux 佈置教學
下一篇
[day22]Redux devtools調試工具
系列文
雙向奔赴的websocket與冰冷的react30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言