四. redux 学习进阶---Redux常用中间件

redux 学习进阶

Redux-thunk

四.Redux常用中间件

4.1 Redux-thunk

4.1.1 Redux-thunk 下载
$	npm install redux-thunk

使用插件就不需要我们去手写中间件了

4.1.2 引入redux-thunk
import thunk from 'redux-thunk';
4.1.3 注册redux-thunk
import thunk from 'redux-thunk';

// 注册中间件
export const store = createStore(RootReducer, applyMiddleware(thunk));

4.1.4 使用redux-thunk中间件
const loadPosts = () => async dispatch =>{
    const posts = await axios.get('/api/posts').then(response=>response.data)
    dispatch({type:LOAD_POST_SUCCESS, payload:posts })
}

action中调用如下

.\store\actions\counter.actions.js

export const addCount_async = (payload)=> (dispatch)=>{
    setTimeout(()=>{
        // 两秒后派发dispatch ,到reducer 处理
        dispatch(addCount(payload))
        // 等价于这个
        // dispatch({type:INCREMENT, payload })
    },2000)
}


redux-saga

https://github.com/dL-hx/react-redux-guide

feat/2.0.0分支

4.2 redux-saga

文档学习:

https://redux-saga-in-chinese.js.org/docs/introduction/BeginnerTutorial.html

API_DOC:

https://redux-saga-in-chinese.js.org/docs/api/

4.2.1 redux-saga解决的问题

redux-saga可以将异步操作从Action Creater文件中抽离出来, 放在一个单独的文件中.

比redux-thunk 更好用,功能类似

4.2.2 redux-saga 下载
$	npm install redux-saga --save
4.2.3 创建redux-saga 中间件
import createSagaMiddleware from 'redux-saga';
const sagaMiddleware = createSagaMiddleware();

sagaMiddleware注册给store

4.2.4 注册redux-saga
createStore(RootReducer, applyMiddleware(sagaMiddleware));
4.2.5 使用saga接收action执行异步操作

https://github.com/dL-hx/react-redux-guide

feat/2.0.0分支

import {takeEvery, put} from 'redux-saga/effects';// 引入两个异步方法

function* load_post(){
    const {data} = yield axios.get('/api/posts.json');
    // put: 用来触发另外一个action,当异步操作时候,  触发action reducer,保存状态
    yield put(load_posts_success(data))
}

// saga:文件中,  要求默认导出一个generater 函数
export default function* postSaga(){
    // takeEvery:用来接收action,通过takeEvery方法接收组件触发的action
    
    // 接收到的action类型string,    接收这个action 需要执行的方法
    yield takeEvery(LOAD_POSTS, load_posts)
}
4.2.6 启动saga

目的:这样做,所写的saga文件才会被加入到redux的工作流中.

import postSaga from './store/sagas/post.saga';

sagaMiddleware.run(postSaga)

.\store\index.js

import { createStore, applyMiddleware } from "redux";
// import reducer from './reducers/counter.reducer'
// 改为合并后的reducers
import RootReducer from "./reducers/root.reducer";

import createSagaMiddleware from 'redux-saga'

import counterSaga from './sagas/counter.saga';


// 创建sagaMiddleware,创建中间件
const sagaMiddleware = createSagaMiddleware()

// 注册redux-saga
export const store = createStore(RootReducer, applyMiddleware(sagaMiddleware));

// 启动counterSaga, 这样才会加入redux工作流中
sagaMiddleware.run(counterSaga)

.\store\actions\counter.actions.js

import { INCREMENT ,DECREMENT , INCREMENT_ASYNC } from "../const/counter.const";
//---------------=> action 对象
export const addCount = (payload)=> ({type:INCREMENT, payload })

...

+ export const addCount_async = ()=> ({type: INCREMENT_ASYNC })

.\store\sagas\counter.saga.js

import { takeEvery, put , delay } from "redux-saga/effects"; // 引入两个异步方法
import { addCount } from "../actions/counter.actions";
import { INCREMENT_ASYNC } from "../const/counter.const";
// takeEvery 接收action
// put 触发action


function* addCount_async_fn(){
   // 执行异步操作
   // 注意: 在generater函数中,   延迟不能使用setTimeout

   // 1. 暂停延迟2s
   yield delay(2000)
   // 2. put 触发action,更新了reducer
   yield put(addCount(10))
}



// saga文件默认要求: 导出一个generater函数
export default function* counterSaga() {
  // 接收action
  // 参数1:接收类型字符串
  // 参数2:异步方法执行的函数.
  yield takeEvery(INCREMENT_ASYNC, addCount_async_fn);
}

页面调用

   <button onClick={addCount_async}>+ 5 </button>

redux-saga传参

https://github.com/dL-hx/react-redux-guide

feat/2.1.0分支

页面调用

 <button onClick={()=>addCount_async_1(20)}>+ 5 </button>

.\store\sagas\counter.saga.js

export const addCount_async_1 = (payload)=> ({type: INCREMENT_ASYNC, payload })

.\store\sagas\counter.saga.js

...

function* addCount_async_1_fn(action){
   yield delay(2000)

    // 从形参中, 获取页面层组件,   传递来的参数
//    yield put(addCount(10))
     // 再次触发action, 修改state状态
   yield put(addCount(action.payload))
}



// saga文件默认要求: 导出一个generater函数
export default function* counterSaga() {
  // 接收action
  // 参数1:接收类型字符串
  yield takeEvery(INCREMENT_ASYNC, addCount_async_1_fn);
}

redux-saga拆分合并

https://github.com/dL-hx/react-redux-guide

feat/2.2.0分支


saga组件拆分

.\store\sagas\counter.saga.js

import { takeEvery, put, delay } from "redux-saga/effects"; // 引入两个异步方法
import { addCount } from "../actions/counter.actions";
import { show } from "../actions/modal.actions";
import { INCREMENT_ASYNC } from "../const/counter.const";
import { SHOW_MODAL_ASYNC } from "../const/modal.const";
// takeEvery 接收action
// put 触发action

function* addCount_async_1_fn(action) {

  // 1. 暂停延迟2s
  yield delay(2000);
  // 2. put 触发action
  //    yield put(addCount(10))
  yield put(addCount(action.payload));
}

function* show_async_fn(action) {
  // 1. 暂停延迟2s
  yield delay(2000);

  yield put(show());
}

// saga文件默认要求: 导出一个generater函数
export default function* counterSaga() {
  // 接收action
  // 参数1:接收类型字符串
  yield takeEvery(INCREMENT_ASYNC, addCount_async_1_fn);

  yield takeEvery(SHOW_MODAL_ASYNC, show_async_fn);
}

// 因为如果不拆分, 这个saga文件就会变得很臃肿, 所以需要拆分

.\store\sagas\counter.saga.js

import { takeEvery, put, delay } from "redux-saga/effects"; // 引入两个异步方法
import { addCount } from "../actions/counter.actions";
import { INCREMENT_ASYNC } from "../const/counter.const";
// takeEvery 接收action
// put 触发action

function* addCount_async_1_fn(action) {
  // 执行异步操作
  // 注意: 在generater函数中,   延迟不能使用setTimeout

  // 1. 暂停延迟2s
  yield delay(2000);
  // 2. put 触发action
  //    yield put(addCount(10))
  yield put(addCount(action.payload));
}


// saga文件默认要求: 导出一个generater函数
export default function* counterSaga() {
  // 接收action
  // 参数1:接收类型字符串
  yield takeEvery(INCREMENT_ASYNC, addCount_async_1_fn);

}

.\store\sagas\modal.saga.js

import { takeEvery, put, delay } from "redux-saga/effects"; // 引入两个异步方法
import { show } from "../actions/modal.actions";
import { SHOW_MODAL_ASYNC } from "../const/modal.const";
// takeEvery 接收action
// put 触发action

function* show_async_fn(action) {
  // 1. 暂停延迟2s
  yield delay(2000);

  yield put(show());
}

// saga文件默认要求: 导出一个generater函数
export default function* modalSaga() {
  // 接收action
  // 参数1:接收类型字符串

  yield takeEvery(SHOW_MODAL_ASYNC, show_async_fn);
}

.\store\sagas\root.saga.js

组合saga文件

import { all } from "redux-saga/effects"; // 引入all方法

import counterSaga from "./counter.saga";
import modalSaga from "./modal.saga";

// saga文件默认要求: 导出一个generater函数
// 通过all方法导出saga文件
export default function* rootSaga() {
  yield all([counterSaga(), modalSaga()]);
}

在修改store/index.js文件

进行注册

import { createStore, applyMiddleware } from "redux";
// import reducer from './reducers/counter.reducer'
// 改为合并后的reducers
import RootReducer from "./reducers/root.reducer";


import createSagaMiddleware from 'redux-saga'

// import counterSaga from './sagas/counter.saga';

import rootSaga from './sagas/root.saga';


// 创建sagaMiddleware,创建中间件
const sagaMiddleware = createSagaMiddleware()

// 注册redux-saga
export const store = createStore(RootReducer, applyMiddleware(sagaMiddleware));

// 启动counterSaga, 这样才会加入redux工作流中
// sagaMiddleware.run(counterSaga)
sagaMiddleware.run(rootSaga)

redux-actions

https://github.com/dL-hx/react-redux-guide

feat/2.3.0分支

redux-actions解决的问题

相关文章:

https://zhuanlan.zhihu.com/p/273569290

4.3 redux-actions

4.3.1 redux-actions 解决的问题

redux流程中大量的样板代码读写很痛苦,

,如action, reducer, const,等

使用redux-actions 可以简化Action和Reducer的处理.

4.3.2 redux-actions 下载
$	npm install redux-actions --save
    1. 用于简化action代码
    1. 用于简化reducer代码
4.3.3 创建 Action

使用了redux-actions 这个函数 actions 就不需要自己去定义了

  1. (之前) 手动定义action_create函数

    export const addCount = (payload)=> ({type:INCREMENT, payload })
    
  2. (现在) 通过 ‘redux-actions’ 自动生成该函数,

    使用时候,不用定义type 常量, redux-action的中间件

import { createAction } from 'redux-actions';

const increment_action = createAction('increment');
const decrement_action = createAction('decrement');
4.3.4 创建 Reducer

redux-actions 简化reducer

简化前

counter.reducer.js

import { INCREMENT, DECREMENT } from "../const/counter.const";

const initialState = {
  count: 0,
};

function reducer(state = initialState, actions) {
  switch (actions.type) {
    case INCREMENT: // 数值 + 1 ,返回一个新对象
      return {
        ...state,
        // count: state.count + 1,
        count: state.count + actions.payload,
      };

    case DECREMENT:
      return {
        ...state,
        // count: state.count - 1,
        count: state.count - actions.payload,
      };

    default:
      return state;
  }
}

export default reducer;

简化后

import {handleActions as createReducer } from 'redux-actions';

import { addCount_Action, minusCount_Action } from '../actions/counter.actions';

const initialState = { count: 0 }

const counterReducer = createReducer({
  [addCount_Action]:(state, actions)=>({
    ...state,
    // count: state.count + 1,
    count: state.count + actions.payload,
  }),


  [minusCount_Action]:(state, actions)=>({
    ...state,
    // count: state.count - 1,
    count: state.count - actions.payload,
  })

}, initialState)

export default counterReducer;

.\store\actions\counter.actions.js

将简化常量文件的定义, 因为后面将通过addCount_Action,这个方法去定义了

createAction: 自动添加了payload方法

import { createAction } from 'redux-actions';

// import { INCREMENT ,DECREMENT , INCREMENT_ASYNC } from "../const/counter.const";

export const addCount_Action = createAction('increment');
// export const addCount_Action = createAction(INCREMENT);

// export const minusCount_Action = createAction(DECREMENT);
export const minusCount_Action = createAction('decrement');

调用

点击按钮时候, 传递到reducer中自动处理, 从而减少了代码量

      <button onClick={()=>addCount_Action(20)}>+ 20</button>
	  <button onClick={()=>minusCount_Action(5)}>- 5</button>

createAction 给我们创建了变量 action 这样就避免了我们在其他文件到处使用字符串 action。

handleActions 给我们生成了 reducer 丰富了reducer 中处理功能,这就是我在大前端训练营所接触的冰山一角。

上一篇:
三. redux 学习进阶—Redux 中间件
下一篇
五. redux 学习进阶—Redux shopping实战案例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值