React学习笔记——Redux基础篇

Redux,状态管理器,将state进行统一的管理,适用于复杂的用户操作、需要协同的用户操作、涉及到权限的网页、多数据源等场景。

基本概念

action:顾名思义,动作。需要执行怎样的操作,action是一个对象,内部包含了此action的类型和相关信息,规范的action如下:

 {
     type:"action_type",
     payload:"message_with_action"
 }

每次都写一遍action非常的蛋疼,所以可以自己设定一个function去生成固定的规范的action,这样一定程度上避免了拼写错误等操作

function createAction(text) {
  return {
    type: ADD_TODO,
    text:"message_with_action"
  }
}

store,存储数据(state)的地方,全局只能有一个store可以通过Redux提供的createStore来创建

import { createStore } from 'redux';
const store = createStore(reducer);

state,真正持有数据的对象,可以通过store.getState()来得到

三大设计原则

  • 单一数据源
    整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
  • State 是只读的
    惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
  • 纯函数
    为了描述 action 如何改变 state tree ,你需要编写 reducers。

事物处理中心Reducer

Reducer应是一个纯函数,接收当前state和action,根据不同的action来返回一个新的state。

const chatReducer = (state = {}, action = {}) => {
  const { type, payload } = action;
  switch (type) {
    case ADD_CHAT:
      return Object.assign({}, state, {
        chatLog: state.chatLog.concat(payload)
      });
    case CHANGE_STATUS:
      return Object.assign({}, state, {
        statusMessage: payload
      });
    case CHANGE_USERNAME:
      return Object.assign({}, state, {
        userName: payload
      });
    default: return state;
  }
};

当存在非常多的action,如果无法对这些action进行区分,Reducer将会变得非常的庞大复杂难以阅读,因此Redux官方提供了一个方法combineReducers让我们可以分开写不同的function来处理相似类型的action(action具体怎么分看,视情况而定),应用如下:

//state结构如下
{
  visibilityFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Consider using Redux',
      completed: true,
    },
    {
      text: 'Keep all state in a single tree',
      completed: false
    }
  ]
}
//拆分后的Reducer
import { combineReducers, createStore } from 'redux'

function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case TOGGLE_TODO:
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: !todo.completed
          })
        }
        return todo
      })
    default:
      return state
  }
}

function visibilityFilter(state = SHOW_ALL, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return action.filter
    default:
      return state
  }
}

function todoApp(state = {}, action) {
  return {
    visibilityFilter: visibilityFilter(state.visibilityFilter, action),
    todos: todos(state.todos, action)
  }
}
//通过combineReducers重新组合
const todoApp = combineReducers({
  visibilityFilter,
  todos
})

export default todoApp

这种写法有一个前提,就是 State 的属性名必须与子 Reducer 同名。如果不同名,就要采用下面的写法。

const reducer = combineReducers({
  a: doSomethingWithA,
  b: processB,
  c: c
})
//与上面的写法等价
function reducer(state = {}, action) {
  return {
    a: doSomethingWithA(state.a, action),
    b: processB(state.b, action),
    c: c(state.c, action)
  }
}

总的来说,即将原本单个总的Reducer拆分成了:单个主Reducer、若干个子Reducer。主Reducer负责选择子Reducer并分发相应部分的state数据。子Reducer专注于处理state当中的一部分内容

存储器Store

store.getState:获取最新的state,此函数将返回一个state;
store.dispatch:分发action,在const store=creatStore(reducer)的情况下会在执行dispatch后自动触reducer;
store.subscribe:注册一个监听器,在stroe.dispatch()后将以此执行监听器,此函数返回一个函数,调用返回的函数即可解除监听器

let unsubscribe = store.subscribe(() =>
  console.log(store.getState())
);

unsubscribe();

Redux工作流程

  1. 用户触发操作激活store.dispatch()
  2. store函数调用reducer,并传入两个参数当前state与action;
  3. state发生变化触发listener;
  4. 如果listener内获取了最新的state并setState,将会进入React的更新流程;

可用的建议

  • 将action定义为常量,并参照规范设计相应action;
 /*
 * action 类型
 */
export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO'
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'

参考:
1. 阮一峰Redux入门教程
2. Redux中文文档
3. action规范

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值