reduxjs/toolkit 结合 redux-saga

171 阅读2分钟

reduxjs/toolkit 结合 redux-saga

  1. 目录说明:

src/
┣ store/
┃ ┣ mySaga/ redux-saga ┃ ┃ ┣ hello.ts
┃ ┃ ┣ index.ts
┃ ┃ ┣ modifyUserName.ts
┃ ┃ ┗ watchAddNumber.ts
┃ ┣ reducer/ reducer ┃ ┃ ┣ counterSlice.ts
┃ ┃ ┣ index.ts
┃ ┃ ┗ userSlice.ts
┃ ┗ index.ts store ┣ App.css
┣ App.js
┣ App.test.js
┣ index.css
┣ index.js
┣ logo.svg
┣ reportWebVitals.js
┗ setupTests.js

  1. 安装依赖
yarn add react-redux reduxjs/toolkit redux-saga
  1. 源码

store —>

index.ts

import { configureStore } from "@reduxjs/toolkit";
import createSagaMiddleware from "redux-saga";
import rootReducers from "./reducer/index.ts";
import mySaga from "./mySaga/index.ts";
const sagaMiddleware = createSagaMiddleware();

const store = configureStore({
  reducer: rootReducers,
  middleware: [sagaMiddleware],
});
// 运行saga
sagaMiddleware.run(mySaga);
export default store;

mySaga —>

hello.ts

// import { put, takeLatest, fork, call } from "redux-saga/effects";

// 其他saga
function* helloSaga() {
    yield console.log("hello,saga-start");
}

export default helloSaga;

index.ts

import { all } from "redux-saga/effects";
// put 它是saga提供给我们,用于发送指令给reducer来完成同步操作
// takeEvery 监听每一次dispatch发送的指令
import helloSaga from "./hello.ts";
import watchSaga from "./watchAddNumber.ts";
import modifyUserName from "./modifyUserName.ts";

// saga中间件 主saga,使用all,多模块操作
function* mySaga() {
  yield all([helloSaga(), watchSaga(), modifyUserName()]);
}

export default mySaga;

modifyUserName.ts

import { put } from "redux-saga/effects";

import { changeName } from "../reducer/userSlice.ts";
// 修改username
function* modifyUserName() {
  yield put(changeName("sagaName"));
}

export default modifyUserName;

watchAddNumber.ts

import { put, takeEvery, delay } from "redux-saga/effects";
import { incrementByAmount } from "../reducer/counterSlice.ts";

// 延时器
// function delay(n = 1) {
//     return new Promise((_) => {
//         console.log("n", n);
//         setTimeout(() => _(""), 1000 * n);
//     });
// }

// 监听saga,监听type类型为异步操作名称的,此saga会通过主saga分配过来
// 其实较与原来的type,这里工具action执行的type获取 
// 最终为"counter/incrementByAmount"
function* watchSaga() {
  yield takeEvery(incrementByAmount(100).type, workSaga_addNumber);
}

// 工作saga,监听saga得到任务后,把任务分配给工作saga
function* workSaga_addNumber(action) {
  console.log("action", action);
  // 每2s,自动计数
  // 异步请求
  // yield call(delay, 2);
  yield delay(2000);
  // dispatch
  yield put(incrementByAmount(action.payload));
}

export default watchSaga;

reducer —>

counterSlice.ts

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

export const counterSlice = createSlice({
  name: "counter",
  initialState: {
    value: 0,
  },
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;

index.ts

import { combineReducers } from "@reduxjs/toolkit";
import counterSlice from "./counterSlice.ts";
import userSlice from "./userSlice.ts";

const reducers = { counter: counterSlice, user: userSlice };

const rootReducers = combineReducers(reducers);

export default rootReducers;

userSlice.ts

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

export const userSlice = createSlice({
  name: "user",
  initialState: {
    name: "jhawn",
  },
  reducers: {
    changeName: (state, action) => {
      state.name = action.payload;
    },
  },
});

export const { changeName } = userSlice.actions;
export default userSlice.reducer;

src —>

App.js

import React from "react";
import "./App.css";
import { useSelector, useDispatch } from "react-redux";
// 引入counter的actions
import {
  increment,
  decrement,
  incrementByAmount,
} from "./store/reducer/counterSlice.ts";
// 引入user的actions
import { changeName } from "./store/reducer/userSlice.ts";
function App() {
  const dispatch = useDispatch();
  // 获取值
  const count = useSelector((state) => state.counter.value);
  const user = useSelector((state) => state.user);
  console.log("count", count);
  console.log("user", user);
  return (
    <div>
      <div>count: {count}</div>
      <button
        onClick={() => {
        // 触发
          dispatch(increment());
        }}
      >
        +
      </button>
      <button
        onClick={() => {
          dispatch(decrement());
        }}
      >
        -
      </button>
      <button
        onClick={() => {
          dispatch(incrementByAmount(10));
        }}
      >
        amout
      </button>
      <div>username: {user.name}</div>
      <button
        onClick={() => {
          dispatch(changeName("testName"));
        }}
      >
        修改名称
      </button>
    </div>
  );
}

export default App;

index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
// 注册store
import store from "./store/index.ts";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();