redux简介

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。Redux 除了和 React 一起用外,还支持其它界面库。

安装

使用npm安装npm install --save redux或者使用yarn安装yarn add redux

redux flow

image-20201226135633302

三大原则

  • 唯一数据源
  • 保持只读状态
  • 数据改变只能通过纯函数来执行

这里的纯函数指的就是reducer,随着应用变大,可以拆分成多个reducer

核心

Action

action负责将数据从应用传输到store,通过store.dispatch()将action传到store;action本质上是JavaScript对象,通过键值来传递数据,规定必须要有type属性,通过type来标识action,此外可以添加其他属性,结构如下:

{
  type: 'ADD_ITEM',
  content: 'code review'
}

Reducer

reducer的主要功能是将action发送到store从而更新store,(previousState, action) => newState,reducer函数接收两个参数,一个是旧的state,另一个是action,返回值是一个新的state。reducer通过action的type属性来识别不同的操作

reducer一定要是一个纯函数,不要在reducer中发生以下操作:

  • 修改传入参数
  • 调用非纯函数
  • 执行有副作用的操作

纯函数:函数的输出结果只跟传入的参数有关,只要参数不变,输出的结果永远不会改变

返回值的操作:不能修改原有的state,可以使用Object.assign({}, state, {newProperty})...(展开运算符)来处理返回结果;遇到无法识别的action时要返回旧的state

拆分reducer:当reducer变得非常复杂时可以将其按照功能拆分,多个reducer通过combineReducers函数来合并或者通过function包装,例如

// todoReducer
const todoState = [
  'test',
  'code',
  'submit',
]
function todoReducer(state = todoState, action) {
  switch(action.type) {
    case 'ADD_ITEM':
      let newState = JSON.parse(JSON.stringify(state))
      newState.push(action.value)
      return newState
    default:
      return state
  }
}
// roleReducer
function roleReducer(state = 'SHOW_ALL', action) {
  switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
      return action.filter
    default:
      return state
  }
}
// index
import { combineReducers, createStore } from 'redux'
let reducer = combineReducers({ todoReducer, roleReducer })
let store = createStore(reducer)
// 或者
export default function todoApp(state = {}, action) {
  return {
    todoReducer: todoReducer(state.todoReducer, action),
    roleReducer: roleReducer(state.roleReducer, action)
  }
}

Store

redux中只有一个store,是负责将action和state联系起来的容器,提供了更新state的方法dispatch()和获取state的方法getState(),通过subscribe()注册监听器以及销毁监听器

暴露store:

在store文件中引入redux中的createStore方法,引入reducers,然后暴露store

import {createStore} from 'redux'
import reducer from './reducer'
let store = createStore(reducer, 
                        window.__REDUX_DEVTOOLS_EXTENSION__ 
                        && window.__REDUX_DEVTOOLS_EXTENSION__())

export default store

createStore()的第二个参数可选,填入这段代码可以开启redux devtools进行调试

订阅store以及获取state:

使用store.getState()可以获取到store中的state,在componentDidMount生命周期中添加订阅

constructor(props) {
  super(props);
  this.state = {
    ...store.getState(),
  }
  // 也可以在这里注册
  // store.subscribe(() => {
  // 	this.setState(store.getState())
    // })

}

componentDidMount() {
  store.subscribe(this.storeChange)
}

storeChange = () => {
  this.setState(store.getState())
}

subscribe()的参数是一个回调函数,当store中数据发生改变时可以触发方法

更新state:

使用store.dispatch()方法,传入action来更新state

addItem = () => {
  if (this.state.input) {
    const action = {
      type: 'ADD_ITEM',
      value: this.state.input
    }
    store.dispatch(action)
    this.setState({
      input: ''
    })
  }
}

前端小白