概述
redux 学习进阶
文章目录
- redux 学习进阶
- Redux-thunk
- 四.Redux常用中间件
- 4.1 Redux-thunk
- 4.1.1 Redux-thunk 下载
- 4.1.2 引入redux-thunk
- 4.1.3 注册redux-thunk
- 4.1.4 使用redux-thunk中间件
- redux-saga
- 4.2 redux-saga
- 4.2.1 redux-saga解决的问题
- 4.2.2 redux-saga 下载
- 4.2.3 创建redux-saga 中间件
- 4.2.4 注册redux-saga
- 4.2.5 使用saga接收action执行异步操作
- 4.2.6 启动saga
- redux-saga传参
- redux-saga拆分合并
- redux-actions
- 4.3 redux-actions
- 4.3.1 redux-actions 解决的问题
- 4.3.2 redux-actions 下载
- 4.3.3 创建 Action
- 4.3.4 创建 Reducer
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中调用如下
.storeactionscounter.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)
.storeindex.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)
.storeactionscounter.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 })
.storesagascounter.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>
.storesagascounter.saga.js
export const addCount_async_1 = (payload)=> ({type: INCREMENT_ASYNC, payload })
.storesagascounter.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组件拆分
.storesagascounter.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文件就会变得很臃肿, 所以需要拆分
.storesagascounter.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);
}
.storesagasmodal.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);
}
.storesagasroot.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
-
- 用于简化action代码
-
- 用于简化reducer代码
4.3.3 创建 Action
使用了redux-actions 这个函数 actions 就不需要自己去定义了
(之前) 手动定义action_create函数
export const addCount = (payload)=> ({type:INCREMENT, payload })
(现在) 通过 ‘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;
.storeactionscounter.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实战案例
最后
以上就是饱满跳跳糖为你收集整理的四. redux 学习进阶---Redux常用中间件redux 学习进阶的全部内容,希望文章能够帮你解决四. redux 学习进阶---Redux常用中间件redux 学习进阶所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复