当前位置: 首页 > news >正文

Redux的使用

到如今redux的已经不是react程序中必须的一部分内容了,

我们应该在本地需要大量更新全局变量时才使用它!

redux vs reducer 

reducer的工作机制:

手动构造action对象传入dispatch函数中

dispatch函数将 action传入reducer当中

reducer结合当前state与action生成新的state 

重新渲染 

 redux的工作机制:

其中store中有多个reducer

单独编写生成action的函数,集中管理action 

传统实现案例

import { createStore } from "redux";const initialState = {balance: 0,loan: 0,loanPurpose: "",
};function reducer(state = initialState, action) {switch (action.type) {case "account/deposit":return {...state,balance: state.balance + action.payload,};case "account/withdraw":return {...state,balance: state.balance - action.payload,};case "account/requestLoan":if (state.loan > 0) return state;return {...state,loan: action.payload.amount,loanPurpose: action.payload.loanPurpose,balance: state.balance + action.payload.amount,};case "account/payLoan":return {...state,loan: 0,loanPurpose: "",balance: state.balance - state.loan,};default:return state;}
}const store = createStore(reducer);store.dispatch({ type: "account/deposit", payload: 500 });console.log(store.getState());

这与reducer的实现非常相似 

我们不能一直手写类型,这非常不方便。所以要有相关函数来做这部分内容。

import { createStore } from "redux";const initialState = {balance: 0,loan: 0,loanPurpose: "",
};function reducer(state = initialState, action) {switch (action.type) {case "account/deposit":return {...state,balance: state.balance + action.payload,};case "account/withdraw":return {...state,balance: state.balance - action.payload,};case "account/requestLoan":if (state.loan > 0) return state;return {...state,loan: action.payload.amount,loanPurpose: action.payload.loanPurpose,balance: state.balance + action.payload.amount,};case "account/payLoan":return {...state,loan: 0,loanPurpose: "",balance: state.balance - state.loan,};default:return state;}
}const store = createStore(reducer);function deposit(payload) {return { type: "account/deposit", payload: payload };
}function withdraw(payload) {return { type: "account/withdraw", payload: payload };
}function requestLoan(payload) {return { type: "account/requestLoan", payload: payload };
}function payLoan(payload) {return { type: "account/payLoan" };
}store.dispatch(deposit(500));
store.dispatch(withdraw(200));
store.dispatch(requestLoan({ amount: 1000, loanPurpose: "Buy a car" }));
store.dispatch(payLoan());

redux中一般store中有多个reducer,我们可以组织代码如下:

accountSlice文件中放置account相关的state:

const initialState = {balance: 0,loan: 0,loanPurpose: "",
};export default function accountReducer(state = initialState, action) {switch (action.type) {case "account/deposit":return {...state,balance: state.balance + action.payload,};case "account/withdraw":return {...state,balance: state.balance - action.payload,};case "account/requestLoan":if (state.loan > 0) return state;return {...state,loan: action.payload.amount,loanPurpose: action.payload.loanPurpose,balance: state.balance + action.payload.amount,};case "account/payLoan":return {...state,loan: 0,loanPurpose: "",balance: state.balance - state.loan,};default:return state;}
}export function deposit(amount) {return { type: "account/deposit", payload: amount };
}export function withdraw(amount) {return { type: "account/withdraw", payload: amount };
}export function requestLoan(payload) {return { type: "account/requestLoan", payload: payload };
}export function payLoan() {return { type: "account/payLoan" };
}

customerSlice文件中放置customer相关的state:

const initialCustormerState = {fullName: "",nationalID: "",createdAt: "",
};export default function customerReducer(state = initialCustormerState, action) {switch (action.type) {case "customer/createCustomer":return {...state,fullName: action.payLoad.fullName,nationalID: action.payLoad.nationalID,createdAt: action.payLoad.createdAt,};case "customer/updateName":return {...state,fullName: action.payLoad.fullName,};default:return state;}
}export function createCustomer(fullName, nationalID) {return {type: "customer/createCustomer",payLoad: {fullName: fullName,nationalID: nationalID,createdAt: new Date().toISOString(),},};
}export function updateName(fullName) {return {type: "account/updateName",payLoad: fullName,};
}

store文件中对reducer进行组合:

import { createStore, combineReducers } from "redux";
import customerReducer from "./features/customer/customerSlice";
import accountReducer from "./features/account/accountSlice";const rootReducer = combineReducers({customer: customerReducer,account: accountReducer,
});const store = createStore(rootReducer);export default store;

导入index.js中即可:

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import store from "./store";const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<React.StrictMode><App /></React.StrictMode>
);

然后将redux与react联系起来,这与contextAPI非常相似,提供一个Provider,并且传入store:

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

然后各个组件中就可以通过useSelector hook获取store中的state,通过useDispatch hook就可以获取dispatch传递action

import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { deposit, payLoan, requestLoan, withdraw } from "./accountSlice";function AccountOperations() {const [depositAmount, setDepositAmount] = useState("");const [withdrawalAmount, setWithdrawalAmount] = useState("");const [loanAmount, setLoanAmount] = useState("");const [loanPurpose, setLoanPurpose] = useState("");const [currency, setCurrency] = useState("USD");const { loan: currentLoan, loanPurpose: currencyLoanPurpose } = useSelector((store) => store.account);const dispatch = useDispatch();function handleDeposit() {if (!depositAmount) return;dispatch(deposit(depositAmount));setDepositAmount("");}function handleWithdrawal() {if (!withdrawalAmount) return;dispatch(withdraw(withdrawalAmount));setWithdrawalAmount("");}function handleRequestLoan() {if (!loanAmount || !loanPurpose) return;dispatch(requestLoan(loanAmount, loanPurpose));setLoanAmount("");setLoanPurpose("");}function handlePayLoan() {dispatch(payLoan());}return (<div><h2>Your account operations</h2><div className="inputs"><div><label>Deposit</label><inputtype="number"value={depositAmount}onChange={(e) => setDepositAmount(+e.target.value)}/><selectvalue={currency}onChange={(e) => setCurrency(e.target.value)}><option value="USD">US Dollar</option><option value="EUR">Euro</option><option value="GBP">British Pound</option></select><button onClick={handleDeposit}>Deposit {depositAmount}</button></div><div><label>Withdraw</label><inputtype="number"value={withdrawalAmount}onChange={(e) => setWithdrawalAmount(+e.target.value)}/><button onClick={handleWithdrawal}>Withdraw {withdrawalAmount}</button></div><div><label>Request loan</label><inputtype="number"value={loanAmount}onChange={(e) => setLoanAmount(+e.target.value)}placeholder="Loan amount"/><inputvalue={loanPurpose}onChange={(e) => setLoanPurpose(e.target.value)}placeholder="Loan purpose"/><button onClick={handleRequestLoan}>Request loan</button></div>{currentLoan > 0 && (<div><span>Pay back {currentLoan} {currencyLoanPurpose}</span><button onClick={handlePayLoan}>Pay loan</button></div>)}</div></div>);
}export default AccountOperations;

middleware 与 redux chunk

由于store本身的局限性无法处理异步情况,所以在dispatch传递时,不直接到reducer中,而是先通过middle ware。而redux chunk就是reudx目前最流行的middle ware第三方库。 

首先在store中进行middle ware的配置: 

import { createStore, combineReducers, applyMiddleware } from "redux";
import { thunk } from "redux-thunk";
import customerReducer from "./features/customer/customerSlice";
import accountReducer from "./features/account/accountSlice";const rootReducer = combineReducers({customer: customerReducer,account: accountReducer,
});const store = createStore(rootReducer, applyMiddleware(thunk));export default store;

 然后在action中进行异步情况的处理:

export function deposit(amount, currency) {if (currency === "USD") return { type: "account/deposit", payload: amount };return async function (dispatch, getState) {dispatch({ type: "account/convertingCurrency" });const res = await fetch(`https://api.frankfurter.app/latest?amount=${amount}&from=${currency}&to=USD`);const data = await res.json();console.log(data);const converted_deposit = data.rates.USD;dispatch({ type: "account/deposit", payload: converted_deposit });};
}

当我们返回的不是一个对象,而是一个函数时,redux就会意识到这个函数是一个“thunk”,redux就不会马上将其传递到store的reducer中,而是会运行这个函数“thunk”,并将dispatch和getState作为函数参数传递到函数“thunk”中。

 

http://www.lryc.cn/news/499751.html

相关文章:

  • 【JAVA】Java高级:多数据源管理与Sharding:数据分片(Sharding)技术的实现与实践
  • ASP.NET Core 9.0 静态资产传递优化 (MapStaticAssets )
  • LeetCode刷题day18——贪心
  • MATLAB Simulink® - 智能分拣系统
  • linuxCNC(五)HAL驱动的指令介绍
  • STM32 进阶 定时器3 通用定时器 案例2:测量PWM的频率/周期
  • 第一节、电路连接【51单片机-TB6600驱动器-步进电机教程】
  • 【通俗理解】Koopman算符与非线性动力系统分析
  • mybatis plus打印sql日志
  • ObjectMapper
  • 新增白名单赋予应用安装权限
  • 传奇996_51——脱下装备,附加属性设为0
  • 【Mac】安装Gradle
  • MySQL中的redoLog
  • Windows 安装 MySQL
  • yocto的xxx.bb文件在什么时候会拷贝文件到build目录
  • Ubuntu Server 22.04.5 LTS重启后IP被重置问题
  • Java基础复习
  • 简易图书管理系统
  • 结构型-组合模式(Composite Pattern)
  • 【知识堂】大数据
  • 力扣C语言刷题记录(三)搜索插入位置
  • 在Node.js局域网调试https的Vue项目
  • 3.5 认识决策树
  • 股市复盘笔记
  • Canal 深入解析:从原理到实践的全面解读
  • SQL SERVER 2016 AlwaysOn 无域集群+负载均衡搭建与简测
  • 解决 Maven 部署中的 Artifact 覆盖问题:实战经验分享20241204
  • 【开源免费】基于SpringBoot+Vue.JS中小型医院网站(JAVA毕业设计)
  • Linux CentOS