redux、react-redux、redux-saga的使用

Redux

安装

# NPM
npm install redux
# Yarn
yarn add redux

state

  • state就是存放数据的地方
  • state数据需要通过reducer来管理
  • 发起reducer需要通过dispatch
  • dispatch的参数是一个action
    总结来说,state的修改需要通过dispatch发起一个action,然后通过reducers返回一个新的state。

Action

  • action是把数据从应用传到store的有效载荷,是store数据的唯一来源。
  • 需要通过store.dispatch()action传到store
  • 格式中type是固定的字段,其他字段可以自定义
// 一个简单的action函数
const ADD_TODO = 'ADD_TODO';
function addTodo(payload) {
    return {
        type: ADD_TODO, // 这里一般会做成一个常量,避免书写是出错
        payload, // 需要传给reducer的数据
    }
}
// 用法
dispatch(addTodo(0))

Reducer

Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新state。

设计state结构

  • 在 Redux 应用中,所有的 state 都被保存在一个单一对象中。

Action 处理

  • 需要通过type区分出来需要如何修改数据,调用不同的方法
  • 修改state的数据,只能返回新的state,不可以直接修改state的数据
  • reducers接受两个参数,一个是state, 一个是action返回的对象
const ADD_TODO = 'ADD_TODO';
// 初始化state
const initialState = {
    todos: []
}
// 处理todos部分的数据
function todos(state = [], action) {
    switch (action.type) {
        case ADD_TODO: 
        return [
            ...state,
            ...action.payload
        ]
        default: 
            return state
    }
   return state;
}

// 统一分配函数,这里讲state的数据分配给不同的方法处理,每个函数只处理state的一部分,如果业务和数据是分开的,可以这样拆分
function todoApp(state, action) {
    return {
        todos: todos(state.todos, action)
    }
}

模块化reducers

在过多的reducers中,可以通过不同的模块进行拆分,然后通过combineReducers将拆分的合并起来。

combineReducers() 所做的只是生成一个函数,这个函数来调用你的一系列 reducer,每个 reducer 根据它们的 key 来筛选出 state 中的一部分数据并处理,然后这个生成的函数再将所有 reducer 的结果合并成一个大的对象。

import { combineReducers } from 'redux'

const todoApp = combineReducers({
    todos, // z这样todos中只能访问到todos的state了,todos就是模块的名称,要访问todos中的数据,需要通过todos.todos来访问
})
// todoApp这两种写法是一样的
function todoApp(state, action) {
    return {
        todos: todos(state.todos, action)
    }
}

export default todoApp

命名空间问题

由于redux并没有采用命名空间这种方式来区分模块,模块在进行diapatch时是对根store抛发的,所以他会触发所有的子reducer,因此各个模块之间要明确好type的格式

Store

创建state

import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp) // 获取所有的state

发起Action,更新数据

import { addTodo } from './actions'
// 这样就可以修改todos的值了
store.dispatch(addTodo('learn about actions'))

react-redux

安装

npm install --save react-redux

传入Store

  • 通过Provider容器讲store传入组件中
  • 最好是讲该容器组件放到根组件中
import React from 'react'
import { Provider } from 'react-redux'
import store from './store/index'
import App from './compontns/App'

render(
    <Provider store={store}>
        <App/>
    </Provider>,
    document.getElementById('root')
)

组件中使用state数据

  • 通过connect将state和dispatch等方法注入到组件里面
  • connect有两个参数mapStateToPropsmapDispatchToProps
  • mapStateToProps是一个函数,接受state作为参数,返回一个对象
  • mapDispatchToProps是函数时:有两个参数,一个是disaptch用来调用action更新store数据,另一个是当前组件的props
  • mapDispatchToProps是对象时:键值应该是一个函数,被当做action,回自动发出该action
// connect
import { connect } from 'react-redux'

// 这里的state是总的那个state
const mapStateToProps = state => {
    return {
        todos: state.todos  // 将todos 返回到组件的props中,key为todos
    }
}

const mapDispatchToProps = (dispatch, ownProps) => {
    return {
    // 这里的方法return后就可以通过props来获取该方法了,在组件中正常进行调用
        onClick: () => {
            dispatch({
                type: ADD_TODO,
                payload: ownProps.todos
            })
        }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Home)// Home是当前组件的名称

redux-saga

安装

npm install redux-sage

yarn add redux-saga

简介

  • redux-saga是一个用于管理redux应用一部操作的中间件
  • redux-saga是通过generator函数创建的

配置

import {createSrote, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import reducers from './reducers';
import rootSaga from './saga' // saga文件

const sageMiddleware = createSagaMiddleware();
// 讲saga引入store中
let store = createStore(reducers, applyMiddleware(sagaMiddleware));
// 运行saga
sagaMiddleware.run(rootSaga);

export default store;

saga方法书写

import { call, put, takeEvery } from 'redux-saga/effects'

const getData = () => {
    // call 是执行异步操作的
    const products = yield call(Api.fetch, '/products')
    // put发起action的和dispatch相似
    yield put({
        type: ADD_TODO,
        payload: products
    })
}

function *stateSaga() {
    yield takeEvery(ADD_TODO, getData)
    yield takeEvery(ADD_TO, getInfo)
}

export const stateSaga = () => {
    
}

总结

  • react-redux是在action发起后监听到需要进行处理的则进行处理,是个在action后面和reducer前面的那一步骤的
  • takeEvery允许多个getData实例同时启动
  • 如果要拦截多个action,可以使用多个takeEvery,不用考虑先后顺序,这个是可以同时触发的。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容