Redux、React-Redux、React-sagas

在一个项目中,除非是小型项目,比如一个个人主页,否则都会涉及到大量的数据传递,如果单纯的用state和props进行组件中的状态管理,在遇到复杂情况时,state和props的传递就会变得很复杂,不仅是给建立项目增加了难度,也给后期维护增加了难度。

Developing modern offline apps with ReactJS, Redux and Electron - Part 3 -  ReactJS + Redux - codecentric AG Blog

所以为了解决这个问题,就需要使用到Redux,并且Redux也是学习React的路上必不可少的一环。

Chrome插件推荐

  • React Developer Tools
  • Redux DevTools 一个使用时间旅行 UI 、热加载和 reducer 错误处理器的 action 日志工具

image-20200905195056265

在浏览器安装这两个插件能更好的管理和Redux中的状态,当然不装也可以。

redux

引入

npm install --save redux redux-saga react-redux

中文文档 英文文档

store.subscribe 订阅改变

store.dispatch(action) 订阅方法

this.state=store.getState();

store.subscribe(this._handleStoreChange) //数据发生改变的时候触发

使用

文件

  • actionCreators.js 调用方法
  • actionTypes.js 规范名称(定义常量)
  • index.js 汇总文件
  • reducer.js 保存数据

index.js

// 添加中间件
import {createStore, applyMiddleware, compose} from "redux";
import createSagaMiddleware from 'redux-saga';

import reducer from "./reducer";
import mySagas from "./sagas";

// 引入中间件
const sagaMiddleware = createSagaMiddleware();

// 引入浏览器插件
const composeEnhancers =
    typeof window === 'object' &&
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
        window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

const enhancer = composeEnhancers(
    applyMiddleware(sagaMiddleware),
);

const store = createStore(reducer, enhancer);
// 执行mySagas文件
sagaMiddleware.run(mySagas);
export default store;

actionCreators.js

import * as actionTypes from "./actionTypes";

//获取文章数据
export const getArticls = () => ({
    type: actionTypes.REQ_ARTICLES,
});

reducer.js

import * as actionTypes from "./actionTypes";

const defaultState = {
    //数据存放
};

export default (state = defaultState, action) => {
    //获取数据
    if (action.type === actionTypes.GET_ARTICLES) {
        const newState = JSON.parse(JSON.stringify(state));
        newState.articles = action.articles;
        return newState;
    }
    return state;
}

中间件

Redux-thunk

安装

yarn add redux-thunk

redux-thunk中间件可以让action创建函数不仅仅返回一个action对象,也可以是返回一个函数。

return (dispatch)=>{
    
}

Redux-saga(大型项目)

安装

yarn add redux-saga

redux-saga是一个用于管理redux应用异步操作的中间件,redux-saga通过创建sagas将所有异步操作逻辑收集在一个地方集中处理,可以用来代替redux-thunk中间件。

sagas.js

  1. sagas是通过generator函数来创建的
  2. sagas监听发起的action,然后决定基于这个action来做什么
  3. 在redux-saga中,所有的任务都通过用yield Effects来完成
  4. redux-saga 为各项任务提供了各种Effects创建器,让我们可以用同步的方式来写异步代码

put

集成

// 添加中间件
import {createStore, applyMiddleware, compose} from "redux";
import createSagaMiddleware from 'redux-saga';

import reducer from "./reducer";
import mySagas from "./sagas";

const sagaMiddleware = createSagaMiddleware();

const composeEnhancers =
    typeof window === 'object' &&
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
        window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose; 

const enhancer = composeEnhancers(
    applyMiddleware(sagaMiddleware),
);

const store = createStore(reducer, enhancer);
//执行mySagas文件
sagaMiddleware.run(mySagas);
export default store;

sagas.js

import {put, takeEvery} from "redux-saga/effects";
import * as actionTypes from "./actionTypes";
import {getArticleTitle, getMassageDataTop, getHeaderImg} from "../server/api";

//方法
function* getArticls() {
    const result = yield getArticleTitle();
    if (result.success_code === 200) {
        const articles = result.data;
        yield put({
            type: actionTypes.GET_ARTICLES,
            articles
        });
    }
}

//存放方法名称
function* mySagas() {
    yield takeEvery(actionTypes.REQ_ARTICLES, getArticls);
}

export default mySagas;

React-redux

安装

yarn add react-redux

避免Redux中store全局化,把store直接集成到React应用的顶层props里面,方便各个子组件能访问到顶层props

let app =
    <Provider store={store}>
        <App/>
    </Provider>;

Provider

将顶层组件包裹在Provider组件之中所有组件就处于react-redux的控制之下了,store作为参数放到Provider组件中,方便其中所有子组件调用

connect方法

export default connect(mapStateToProps, null)(App);

mapStateToProps

把state映射到props中去,意思就是把Redux中的数据映射到React中的props中去

const mapStateToProps = (state) => {
    return {
        
    }
}

mapDispatchToProps 派发

把各种dispatch也变成了props,在组件中可以直接使用避免了手动去用store.subscribe订阅render函数以达到更新页面的目的

const mapDispatchToProps = (dispatch) => {
    return {
        
    }
}