Redux

Redux

Redux 核心原理

  • state
this.state ={
  todos: [{
    text: 'Eat food',
    completed: true
  }, {
    text: 'Exercise',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}

组件状态改变是因为本身state发生setState()

  • action
    action对象,描述要对组件的state做什么样的操作
{
  type: 'ADD_TODO',
  text: 'Go to swimming pool'
}
  • reducer函数
    通过reducer函数将组件原state和对state惊醒更改的action传入reducer函数,利用action对stat进行更改,返回新的state。

  • state 有多种状态,需要多个actio、多个reducer函数去做处理

  • reducer函数
    reducer(原state,action);

action

{
  type: 'ADD_TODO',
  text: 'Go to swimming pool'
}
  • 生成action的action创建函数
function addTodo(name){
  return {
    type:"ADD_TODO",
    name:name
  }
}
  • 创建并且提交
dispatch(addTodo(text))
  • 创建一个 被绑定的 action 创建函数 来自动 dispatch(创建action,返回action,提交action)
const addTodo = name => dispatch(addTodo(name))


//最终redux提供你得函数
addTodo("add");

React-redux 案例

安装

  • redux
  • react-redux
npm install redux react-redux --save

创建工程目录

  • Store 存放与redux相关的文件
    • Actions 存放所有action
    • Reducers 存放reduce
    • actionType.js 存放所有的action的type
    • index.js Redux的入口文件
  • Component 存放react组件

引入 Provider

在项目入口文件index.js中引入 Redux 提供的 Provider 组件

ReactDOM.render(
  <Provider>
    <App />
  </Provider>
, document.getElementById('root'));

创建store

在redux的入口文件中,创建store

  • 引入createStore和combineReducers
    • createStore:创建store
      参数:合并后的reducer
      参数:初始化状态的state(这里写个空对象即可)
    • combineReducers:合并reducer
      参数:对象(多个reduce组成)
import {createStore,combineReducers} from "redux"
import {addTodoItem} from "./Reducers/TodoReducer"

const rootReducer = combineReducers({
  addItem:addTodoItem
});

const initialState = {

};

const store = createStore(rootReducer,initialState);
export default store;

创建store完成后,引入index.js,完成应用入口文件:

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

创建actionType.js文件

actionType.js文件用于保存action对象的type值,因为type值必须为字符串类型,并且
在action创建函数和reducer都要用到action的type属性,所以创建actionType.js文件来
保存,在使用的时候引入即可:

export const ADD_TODO_ITEM = "add_todo_item";
export const CHANGE_PENDDING = "change_pendding";
export const CHANGE_FINISHED = "change_fininshed";
export const DELETE_ITEM = "delete_item";

创建action.js文件

action.js文件把针对一个state进行操作的action创建函数定义在一起

import {ADD_TODO_ITEM,CHANGE_PENDDING,CHANGE_FINISHED,DELETE_ITEM} from "../ActionType";



export function addTodoList(toDoName){
  return {
    type:ADD_TODO_ITEM,
    itemName:toDoName
  }
}

export function penddingToFinished(item){
  return {
    type:CHANGE_PENDDING,
    item:item
  }
}

export function finishedToPendding(item){
  return{
    type:CHANGE_FINISHED,
    item:item
  }
}

export function deleteItem(item){
  return{
    type:DELETE_ITEM,
    item:item
  }
}

创建reducer.js

每一个state对应一个reducer,我们把它定义在一个文件中,并且将组件的初始state也定义在这里,
组件默认回去state都是从这个reducer中获取到的

import {ADD_TODO_ITEM,CHANGE_PENDDING,CHANGE_FINISHED,DELETE_ITEM} from "../ActionType"


const initialState = {
  pendding:[
    // {
    //   status:false,
    //   itemName:"王凯学习迷糊了,已经崩盘中。。。"
    // }
  ],
  finished:[
    // {
    //   status:true,
    //   itemName:"Vue学习",
    // }
  ]
}

export function addTodoItem(state=initialState, action){
  switch(action.type){
    case ADD_TODO_ITEM:
      return{
          pendding:state.pendding.concat({status:false,itemName:action.itemName}),
          finished:state.finished
      }
    case CHANGE_PENDDING:
      state.pendding.map((value,index)=>{
        if(value.itemName === action.item.itemName){
          state.pendding.splice(index,1);
        }
      })
      return{
        pendding:state.pendding,
        finished:state.finished.concat({status:!action.item.status,itemName:action.item.itemName})
      }
    case CHANGE_FINISHED:
      state.finished.map((value,index)=>{
        if(value.itemName === action.item.itemName){
          state.finished.splice(index,1);
        }
      })
      return{
        pendding:state.pendding.concat({status:!action.item.status,itemName:action.item.itemName}),
        finished:state.finished
      }

    case DELETE_ITEM:
      if(action.item.status){
        state.finished.map((value,index)=>{
          if(value.itemName === action.item.itemName){
            state.finished.splice(index,1);
          }
        })
      }else{
        state.pendding.map((value,index)=>{
          if(value.itemName === action.item.itemName){
            state.pendding.splice(index,1);
          }
        })
      }

      return{
        pendding:state.pendding,
        finished:state.finished
      }
    default:
      return state;
  }

}

初始化state的定义一定要跟组件对应

组件相关函数

  • mapStateToProps
    组件接受数据,并且将数据放置在组件的this.props中
  • mapActionToProps
    组件提交对组件state更改的action
  • connect
    将组件接受数据和提交action的函数以及组件与redux中的对应reducer绑定
// 绑定组件对应的reducer,并且接受调用reducer返回新state
function mapStateToProps(state) {
  return{
    state:state.addItem
  }
}

// 提交action到上面那个函数绑定后跟组件对应的reducer
function mapActionToProps(dispatch){
  return {
    addItem:(name)=>{
      dispatch(addTodoList(name))
    },
    changePendding:(item)=>dispatch(penddingToFinished(item)),
    changeFinished:(item)=>dispatch(finishedToPendding(item)),
    deleteItem:(item)=>dispatch(deleteItem(item))
  }
}

export default connect(mapStateToProps,mapActionToProps)(Box);

原理:
mapStateToProps、mapActionToProps都是定义在组件中的回调函数,通过connect函数将他与rootReducer绑定;
connect(mapStateToProps,mapActionToProps)(Box):绑定完成后,给组件this.props返回数据和dispatch函数;
组建可以接受数据和使用提交action的方法接受和提交action
提交action去rootReducer

所有的 reducer 都会收到 action。
reducer 通过 action.type 来进行判定处理。
如果某个 reducer 不处理某个动作,也就是没有处理这个 action.type 的 case, 就会走 default 分支,把 state 原样返回。

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