了解如何使用Redux

Redux是一个状态管理器,通常与React一起使用,但它并不与该库绑定。通过阅读此简单易懂的指南来学习Redux

为什么需要Redux

Redux是一个状态管理器,通常与React一起使用,但它并不与该库绑定-它也可以与其他技术一起使用,但是为了说明起见,我们将坚持使用React。

如您所读,React有其自己的状态管理方式。React初学者指南在这里,我介绍了如何在React中管理状态。

在简单的情况下,将状态在树中上移是可行的,但是在复杂的应用程序中,您可能会发现几乎使用道具向上移动所有状态,然后向下向下移动道具。

React在16.3.0版中引入了上下文API,这使得Redux在从应用程序的不同部分访问状态的用例中变得多余,因此,除非您需要Redux提供的特定功能,否则请考虑使用Context API而不是Redux。

Redux是一种管理应用程序状态并将其移至外部全球商店

您需要掌握一些概念,但是一旦完成,Redux是解决问题的非常简单的方法。

Redux在React应用程序中非常流行,但是它绝不是React独有的:几乎所有流行的框架都有绑定。就是说,我将使用React作为它的主要用例来举例说明。

什么时候应该使用Redux?

Redux是中型到大型应用程序的理想选择,只有在使用默认状态管理React或其他使用的库来管理状态时,才应使用Redux。

简单的应用程序根本不需要它(简单应用程序没有错)。

不变的状态树

在Redux中,应用程序的整个状态表示为 JavaScript对象,称为状态或者状态树

我们称它为不变的状态树因为它是只读的:不能直接更改。

只能通过分派一个行动

动作

一个行动一个以最小方式描述更改的JavaScript对象(仅提供所需的信息):

{
  type: 'CLICKED_SIDEBAR'
}

// e.g. with more data { type: ‘SELECTED_USER’, userId: 232 }

动作对象的唯一要求是拥有一个type属性,其值通常是一个字符串。

动作类型应为常量

在简单的应用程序中,可以将操作类型定义为字符串。

当应用增长时,最好使用常量:

const ADD_ITEM = 'ADD_ITEM'
const action = { type: ADD_ITEM, title: 'Third item' }

并在自己的文件中分离操作,然后将其导入

import { ADD_ITEM, REMOVE_ITEM } from './actions'

动作创作者

动作创作者是创建动作的功能。

function addItem(t) {
  return {
    type: ADD_ITEM,
    title: t
  }
}

通常,您可以结合触发调度程序来运行动作创建者:

dispatch(addItem('Milk'))

或通过定义动作分派器功能:

const dispatchAddItem = i => dispatch(addItem(i))
dispatchAddItem('Milk')

减速器

当一个动作被触发时,必须发生一些事情,应用程序的状态必须改变。

这是工作减速器

什么是减速器

一种减速器是一个纯功能它根据前一个状态树和分派的操作来计算下一个状态树。

;(currentState, action) => newState

纯函数接受输入并返回输出,而不更改输入或其他任何内容。因此,reducer返回一个全新的状态来替代先前的状态。

减速器不应该做什么

减速器应为纯函数,因此应:

  • 永不改变其论点
  • 永远不会改变状态,而是创建一个新的状态Object.assign({}, ...)
  • 永远不会产生副作用(没有API调用会改变任何东西)
  • 永远不要调用非纯函数,这些函数会根据输入以外的因素来改变其输出(例如,Date.now()或者Math.random()

没有强化,但是您应该遵守规则。

多个异径管

由于复杂应用程序的状态可能真的很宽,因此没有单个化简器,而是针对任何类型的动作使用了许多化简器。

减速器的模拟

本质上,Redux可以通过以下简单模型进行简化:

状态

{
  list: [
    { title: "First item" },
    { title: "Second item" },
  ],
  title: 'Groceries list'
}

行动清单

{ type: 'ADD_ITEM', title: 'Third item' }
{ type: 'REMOVE_ITEM', index: 1 }
{ type: 'CHANGE_LIST_TITLE', title: 'Road trip list' }

每个州的减速器

const title = (state = '', action) => {
    if (action.type === 'CHANGE_LIST_TITLE') {
      return action.title
    } else {
      return state
    }
}

const list = (state = [], action) => { switch (action.type) { case ‘ADD_ITEM’: return state.concat([{ title: action.title }]) case ‘REMOVE_ITEM’: return state.filter(item => action.index !== item.index) default: return state } }

整个状态的减速器

const listManager = (state = {}, action) => {
  return {
    title: title(state.title, action),
    list: list(state.list, action)
  }
}

商店

店铺是一个对象:

  • 保持状态该应用程序的
  • 暴露状态通过getState()
  • 允许我们更新状态通过dispatch()
  • 允许我们(取消)注册状态变更监听器使用subscribe()

一家商店是独特的在应用程序中。

这是为listManager应用程序创建商店的方式:

import { createStore } from 'redux'
import listManager from './reducers'
let store = createStore(listManager)

我可以使用服务器端数据初始化存储吗?

当然,刚过一个开始状态

let store = createStore(listManager, preexistingState)

获取状态

store.getState()

更新状态

store.dispatch(addItem('Something'))

聆听状态变化

const unsubscribe = store.subscribe(() =>
  const newState = store.getState()
)

unsubscribe()

数据流

Redux中的数据流始终是单向

你打电话dispatch()在商店中,通过一个动作。

商店负责将操作传递给Reducer,生成下一个状态。

商店会更新状态并警告所有侦听器。

免费下载我的反应手册


更多反应教程: