React-redux

一、认识Redux

安装

npm install --save redux 

npm install --save react-redux

一句话理解Redux

应用中的所有state都以一个对象数树的方式存储在一个单一的store中,唯一改变state的方法就是触发action,一个描述发生什么的对象,为了描述action如何改变state树,需要编写reducers。

什么是Action?

Action本质上是JavaScript的普通对象,action内必须使用一个字符串类型的type字段来表示将要执行的动作。多数情况下type会被定义成字符串常量。我们应该尽量减少在actin中传递数据。

Action:

export const ADD = 'ADD'

export const add = () => ({

   type: ADD

})


export const SUB = 'SUB'

export const sub = () => ({

   type: SUB

})

什么是Reducer?

设计state结构

Action处理

reducer是一个纯函数,接受旧的state和action,返回新的state。

注意: 每个 reducer 只负责管理全局 state 中它负责的一部分。每个 reducer 的 state 参数都不同,分别对应它管理的那部分 state 数据。

Reducer:

import { ADD, SUB } from 'Action'


const counter = (state = 0, action) => {

   switch (action.type) {

       case ADD:

return state + 1

case SUB:

return state - 1

default:

return state

}

}

总结:把要做的修改变成一个普通对象,这个对象叫做action,而不是直接修改state。然后编写专门的函数来决定每个action如何改变应用的state,这个函数叫做reducer。


二、关于Redux的重点知识

1. 三大原则

(1)单一数据源

整个应用的state被存储在一棵object tree中,并且这个object tree只存在于唯一一个store中。

(2)state是只读的

唯一改变state的方法就是触发action,action是一个用于描述已发生事件的普通对象。

(3)使用纯函数来执行修改

为了描述action如何改变state,需要写reducers。

注意:永远不要在reducer中做这些操作

修改传入参数;

执行有副作用的操作,如API请求和路由跳转;

调用非纯函数,如Date.now(), Math.random()。

只要传入参数相同,返回计算得到的下一个state就一定相同。没有特殊情况,没有副作用,没有API请求,没有变量修改,单纯执行计算。

2.combineReducer

为什么使用combineReducer?

随着应用变得复杂,需要对 reducer 函数进行拆分,拆分后的每一块独立负责管理 state 的一部分。


combineReducers 辅助函数的作用是,把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore。


合并后的 reducer 可以调用各个子 reducer,并把它们的结果合并成一个 state 对象。state 对象的结构由传入的多个 reducer 的 key 决定。

import { combineReducer } from 'redux'


const todoApp = combineReducer({

   visibilityFilter,

   todos

})


export default todoApp

等价写法 =>

export const todoApp = (state = {}, action) => {

   return {

       visibilityFilter: visibilityFilter(state.visibilityFilter, action)

       todos: todos(state.todos, action)

   }

}

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

combineReducer示例:

reducers/todos.js

export default function todos(state = [], action) {

 switch (action.type) {

 case 'ADD_TODO':

   return state.concat([action.text])

 default:

   return state

 }

}

reducers/counter.js

export default function counter(state = 0, action) {

 switch (action.type) {

 case 'INCREMENT':

   return state + 1

 case 'DECREMENT':

   return state - 1

 default:

   return state

 }

}

reducers/index.js

import { combineReducers } from 'redux'

import todos from './todos'

import counter from './counter'


export default combineReducers({

 todos,

 counter

})

App.js

import { createStore } from 'redux'

import reducer from './reducers/index'


let store = createStore(reducer)

3.Redux中的connect()方法

(1)定义mapStateToProps方法

把当前Redux store state映射到展示组件的props中。

(2)定义mapDispatchToProps方法

接收dispatch()方法并返回期望注入到展示组件的props中的回调方法。

import { connect } from 'react-redux'

import { Task } from './reducers'


const mapStateToProps = (state) => {

   return {

       tasks: state.entities.tasks

   }

}


const mapDispatchToProps = (dispatch) => {

   return {

       addUnit: (taskID, unitID, units) => {

           dispatch(Task.addUnit(taskID, unitID, units))

       }

   }

}


等价于 =>


const mapDispatchToProps = (dispatch) => {

   return {

       addUnit: (taskID, unitID, units) => Task.addUnit(taskID, unitID, units))

   }

}



//多个conncet的书写方式

const VisibleCreateUnit = connect(

   mapStateToProps,

   mapDispatchToProps

)(CreateUnit)


const VisibleCreateTask = connect(

   mapStateToProps,

   mapDispatchToProps

)(CreateTask)


export { VisibleCreateUnit, VisibleCreateTask }

4.Store

(1)createStore()

createStore() 的第二个参数是可选的, 用于设置 state 初始状态。这对开发同构应用时非常有用,服务器端 redux 应用的 state 结构可以与客户端保持一致, 那么客户端可以将从网络接收到的服务端 state 直接用于本地数据初始化。

(2)Redux Provider

import { Provider } from 'react-redux'

import { createStore } from 'redux'

在React-router中使用Provider

const store = createStore(appReducer, normalizedState)









5.数据序列化(normalize)

示例:Tasks中包含subTasks和units,subTasks中又包含units。

import { normalize, schema } from 'normalizr'


//首先使用schema最小单元即units

const unitsSchema = new schema.Entity('units')

//subTasks中包含units

const subTasksSchema = new schema.Entity('subTasks', { units: [unitsSchema] })

//tasks中包含subTasks和units

const tasksSchema = new schema.Entity('tasks', {

subTasks: [subTasksSchema],

units: [unitsSchema]

})



......

const initialState = {

   tasks: {

       subTasks: {

           units: {

               ......

           }

           ......

       },

       units: {

           ......

       }

   },

   groups: {

       ......

   },

   classes: {

       ......

   },

   rosters: {

       ......

   }

}


const stateSchema = {

   tasks: [tasksSchema],

   groups: [groupsSchema],

   classes: [classesSchema],

   rosters: [rostersSchema]

}


const normalizedState = normalize(initialState, stateSchema)

console.log('normalizedState', normalizedState)


Object{

   entities: Object{

       .....

   }

   result: Object{

       tasks: array[2],

       groups: array[3],

       classes: array[4],

       rosters: array[5]

   }

}

注意:键一定与数组中的键一一对应

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容