首先安装react 脚手架
可以看我的作品
react 脚手架的安装和使用(1) - 掘金 (juejin.cn)
然后删除不必要的文件留下入口文件index.JS和 app.jsx
安装我们需要的依赖
npm install redux react-redux
//安装radux
npm install --save redux-devtools-extension //安装调试工具
当然首先呢我们先用react-redux 写一个 计数器的案例。
首先我们创建一个reducer 函数
当然我们开发肯定是写多个reducer 函数 所以创建一个文件夹使用combineReducers来合并reducer
1.首先创建reducer函数
//ADD,SUB引用的是我写的常量
export const counter =(state={count:0},action)=>{
console.log("调用了counter");
switch (action.type){
case ADD:
return{
count:state.count+1
}
case SUB:
return{
count:state.count-1
}
default :
return state
}
}
然后写合并reducer
//首先我们引用redux 的combinReducers 来合并reducr函数
import { combineReducers } from "redux";
//引用reducer函数
import { counter } from "./counter";
export const rootReducer=combineReducers({
counter
//简写 counter:counter
})
2.然后在入口文件引入模块并且 创建全局store
import React from 'react';
import ReactDOM from 'react-dom/client';
import reportWebVitals from './reportWebVitals';
//composeWithDevTools是监控中间件的
import { composeWithDevTools } from 'redux-devtools-extension';
import { applyMiddleware, legacy_createStore } from 'redux';
import App from './app';
import { rootReducer } from './counter';
import { Provider } from 'react-redux';
//使用legacy_createStore 创建全局store 并把reducer添加进去
let store =legacy_createStore(rootReducer,composeWithDevTools(applyMiddleware()))
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
//通过<Provider store={store}></Provider>将store向后代组件传递
);
3.然后写action (action 是用来修改store数据的)
export const add=()=>{
return {
type:ADD
}
}
export const sub=()=>{
return {
type:SUB
}
}
4.最后我们写组件APP.jsx
import { connect } from "react-redux";
import { add,sub } from "./action";
const App =(props)=>{
let {add,sub,counter}=props
return(
<>
<h3>App组件</h3>
<p>{counter.count}</p>
<button onClick={()=>add()}>+</button>
<button onClick={()=>sub()}> -</button>
</>
)
}
const mapStateToProps=(state,ownProps)=>{
return{
counter:state.counter
}
}
export default connect(mapStateToProps,{add,sub})(App) ;
//connect()
//<1>.调用mapStateToProps函数,将函数返回值和this.propsprops进行合并
//这个函数允许我们将 store 中的数据作为 props 绑定到组件上。
//Object.assign(this.props/props, mapStateToProps函数调用的返回值对象);
//<2>将sotre.dispatch函数添加到组件的this.props/props上
这里我们重点解释一下mapStateToProps
mapStateToProps(state, ownProps) : stateProps
这个函数的第一个参数就是 Redux 的 store,我们从中摘取了 count 属性。你不必将 state 中的数据原封不动地传入组件,可以根据 state 中的数据,动态地输出组件需要的(最小)属性。
(2)函数的第二个参数 ownProps,是组件自己的 props。有的时候,ownProps 也会对其产生影响。
当 state 变化,或者 ownProps 变化的时候,mapStateToProps 都会被调用,计算出一个新的 stateProps,(在与 ownProps merge 后)更新给组件。
最后的效果是一个计数器
复习完react-redux 后我们开始正式的讲redux-saga
首先我们需要引用createSagaMiddleware() 创建中间件
const sagaMiddleware =createSagaMiddleware();
然后注册中间件
let store=legacy_createStore(rootReducer,composeWithDevTools(applyMiddleware(sagaMiddleware)) )
我们创建一个saga文件(也就是generator函数)
export function *hello(){
yield console.log("tom");
yield console.log("jarry");
}
最后使用saga 的run方法 运行
sagaMiddleware.run(hello) //递归遍历generator函数 每个yield的状态
结果就是控制台打印了 tom jarry
saga 的API
1. takeEvery
(1)初始化阶段:注册异步action和工作saga之间的关系
(2)更新阶段:先转发action给reducer函数(刷loading),之后调用工作saga实现业务 (刷数据或错误)(也就是一发送异步action 第一个参数 就调用第二个参数工作saga)
2.put 就相当于 dispatch:功能转发action
3.delay 模拟网络延迟—模拟异步
4. takeLatest 功能类似于takeEvery ,用来阻止重复提交—去抖
5. call 调用异步函数---解决地狱回调—特别注意,加不加call都阻塞执行
call(异步函数,异步的实参);调用异步的时候也是阻塞执行 比如(setTimeout,2000)
6. fork 调用异步函数---非阻塞执行—非地狱回调—同时发送多个异步请求
7. all 同时执行多个异步函数
了解好了之后呢我们补充个小案例
异步+数字
首先添加变量
export const ADDASYNC="ADDASYNC"
然后添加action
export const addAsync=()=>{ return { type:ADDASYNC } }
重新写一个reducer 并且合并
switch (action.type){
default :
return state
}
}
最后写saga文件
import { ADD , ADDASYNC } from "../constants";
//创建work saga
function * gAddAsync(){
yield delay(2000);
yield put({type:ADD})
}
export function * watchgAddAsync (){
yield console.log("watchgAddAsync被调用");
yield takeEvery(ADDASYNC,gAddAsync)
//takeEcery注册了异步action ADDASYNC和 工作saga gaddasync的关系 发送ADDASYNC就调用 gAddAsync
}
//**redux-saga中一个业务需要两种saga:
** 第一种: workSaga: fulfilled/reject**
** 第二种:watchSsaga pending—刷loading**
****
然后写到组件上边去
<button onClick={()=>addAsync()}> async</button>
实现延迟两秒 异步加数字
步骤如下:
然后我们写一个异步获取数据的案例
因为你run()方法只能跑一个函数,所以这里我们利用all方法合并saga
首先我们再写一个saga函数
let res= yield call(axios.get,"https://jsonplaceholder.typicode.com/users")
console.log("res",res);
//随机获取10个数据
}
export function *watchgFetchUser(){
yield takeEvery(FETCH_USER_SUCCESS,gFetchUser)
}
//然后进行合并
export function * rootSaga(){
yield all([
watchgAddAsync(),
watchgFetchUser()
])
}
再写一个action添加方法
export const fetch_user =()=>{
return {
type:FETCH_USER_SUCCESS
}
}
最后我们添加到组件中
<button onClick={()=>fetch_user()}>fetch_user</button>
效果如图