React实战篇——三、Redux简介及其主要组成

三、Redux简介及其主要组成

1,简介

Redux应用需要遵循三大原则,否则程序很容易出现难以察觉的问题。

  ①唯一数据源

  Redux只维护一个全局的状态对象,存储在Redux的store中。唯一数据源是一种集中式管理应用状态的方式,便于监控任意时刻应用的状态和调试应用,减少出错的可能性。

  ②保持应用状态只读

  在任何时候都不能直接修改应用状态。当需要修改应用状态时,必须发送一个action,由这个action描述如何修改应用状态。

  ③应用状态的改变通过纯函数完成

  action表明修改应用状态的意图,真正对应用状态做修改的是reducer。reducer必须是纯函数,所以reducer在接收到action时,不能直接修改原来的状态对象,而是要创建一个新的状态对象返回。

  纯函数指的是:

  • 对于同样的参数值,函数的返回结果总是相同的。
  • 函数的执行不会产生副作用,例如修改外部对象或输出到I/O设备。

2,主要组成

  ①action:是Redux中信息的载体,是store唯一的信息来源。把action发送给store必须通过store的dispatch方法。action是普通的JavaScript对象,但每一个action必须有一个type属性描述action的类型,type一般为字符串常量。除了type属性外,action的结构完全由自己决定。一般通过action creator创建action,action creator是返回action的函数:

export const ADD_TODO = 'ADD_TODO'
export const TOGGLE_TODO = 'TOGGLE_TODO'
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'
// 筛选待办事项列表的条件
export const VisibilityFilters = {
  SHOW_ALL: 'SHOW_ALL',
  SHOW_COMPLETED: 'SHOW_COMPLETED',
  SHOW_ACTIVE: 'SHOW_ACTIVE'
}

//action creators
//新增待办事项
export function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}
//修改待办事项的状态,index是待办事项在todos数组中的位置索引
export function toggleTodo(index) {
  return {
    type: TOGGLE_TODO,
    index
  }
}
//筛选当前显示的待办事项列表
export function setVisibilityFilter(filter) {
  return {
    type: SET_VISIBILITY_FILTER,
    filter
  }
}

  ②reducer:action用于描述应用发生了什么操作,reducer则根据action做出相应,决定如何修改应用的状态state。既然是修改state,那么就应该在编写reducer之前设计好state。state既可以包含服务器端获取的数据,也可以包含UI状态:

{
  todos: [{
    text: 'Learn React',
    completed: true
  },{
    text: 'Learn React',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}

  创建reducer:

import { VisibilityFilters } from './actions'
const initialState = {
  todos: [],
  visibilityFilter: VisibilityFilters.SHOW_ALL
}

//reducer
function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return { ...state, visibilityFilter: action.filter }
    // 新增待办事项
    case ADD_TODO:
      // 使用了ES6的扩展语法
      return {
        ...state, todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      }
    // 修改待办事项的状态(已完成/未完成)
    case TOGGLE_TODO:
      return {
        ...state, todos: state.todos.map((todo, index) => {
          if (index === action.index) {
            return {
              ...todo, completed: !todo.completed
            }
          }
          return todo
        })
      }
    default:
      return state
  }
}

  当应用变得复杂时,这个reducer也会逐渐变复杂,这时,一般会拆分出多个reducer,每个reducer处理state中的部分状态:

todos.js:

const todos = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ]
    case 'TOGGLE_TODO':
      return state.map(todo =>
        (todo.id === action.id) 
          ? {...todo, completed: !todo.completed}
          : todo
      )
    default:
      return state
  }
}

export default todos

visibilityFilter.js:

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

export default visibilityFilter

todoApp.js:

import todos from './todos'
import visibilityFilter from './visibilityFilter'

const todoApp = combineReducers({
  todos,
  visibilityFilter
})

export default todoApp

  每个拆分的reducer只接收它负责的state中的部分属性。Redux还提供了一个combineReducers函数,用于合并多个reducer。

  

  还可以为combineReducers接受的参数对象指定和reducer的函数名不同的key值:

   

   可见,combineReducers传递给每个reducer的state中的属性取决于它的参数对象和key值。

  ③store

  store是Redux中的一个对象,也是action和reducer之间的桥梁。store主要负责以下几个工作:

  • 保存应用状态
  • 通过方法getState()访问应用状态
  • 通过方法dispatch(action)发送更新状态的意图
  • 通过方法subscribe(listener)注册监听函数、监听应用状态的改变

  一个Redux应用中只有一个store,store保存了唯一数据源。store通过createStore()函数创建,创建时需要传递reducer作为参数,创建todos应用的store代码如下:

import { createStore } from 'redux'
import todoApp from './reducers'

const store = createStore(todoApp)

  创建store时还可以设置应用的初始状态:

const store = createStore(todoApp,initialState)

  store创建完成后,就可以通过getState()获取当前应用的状态state:

const store = store.getState()

  当需要修改state时,通过store的dispatch()方法发送action。例如,发送一个新增待办事项的action:

function addTodo(text) {
  return {type: 'ADD_TOTO',text}
}
store.dispatch(addTodo('Learn about actions'))

  当todoApp这个reducer处理完成addTodo这个action时,应用的状态会被更新,此时通过store.getState()可以得到最新的应用状态。为了能准确知道应用状态更新的时间,需要向store注册一个监听函数:

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

  这样每当应用状态更新时,最新的应用状态就会被打印出来。当需要取消监听时,直接调用store.subscribe返回的函数即可:

  unsubscribe();

总结:

  • 调用store.dispatch(action)。一个action是一个用于描述“发生了什么”的对象。store.dispatch(action)可以在应用的任何地方调用,包括组件、XHR回调,甚至在定时器中。
  • Redux的store调用reducer函数。store传递两个参数给reducer:当前应用的状态和action。reducer必须是一个纯函数,它的唯一职责是计算下一个应用的状态。
  • 根reducer会把多个子reducer的返回结果组合成最终的状态。跟reducer的构建形式完全取决于用户。Redux提供了combineReducers,方便把多个拆分的子reducer组合到一起。
  • Redux的store保存根reducer返回的完整应用状态。此时,应用状态才完成更新。如果UI需要根据应用状态进行更新,那么这就是更新UI的时机。对于React而言,可以在此时调用组件的setState方法,根据新的应用状态更新UI。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值