reduxjs/toolkit 结合 redux-saga
- 目录说明:
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
- 安装依赖
yarn add react-redux reduxjs/toolkit redux-saga
- 源码
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();