Redux 教程 - 入门

在前端领域中,状态管理一直是一个非常重要的问题。随着应用程序的复杂度不断增加,用传统的方式进行状态管理已经不再适用了。这时,我们就需要一种有完整的状态管理方案,能够帮我们管理应用程序状态的解决方案。Redux 就是这样一种解决方案。

Redux 是一个 JavaScript 库,它被广泛用于构建单页应用程序(SPA)。Redux 主要被用来简化程序的状态管理,而不是用来解决其它的问题。在 Redux 中,应用程序的状态被描述为一个单一的对象。当状态发生变化时,Redux 会触发一些事件来通知应用程序状态的变化。在这篇文章中,我们将详细介绍如何使用 Redux 来实现状态管理。

1. 概述

1.1 概念

Redux 的核心概念是 Store,Action 和 Reducer。Store 是应用程序状态的唯一来源,在 Store 中存放了所有应用程序的状态。Action 是应用程序状态的变化方式,通过分发 Action,我们可以通知 Store 状态发生变化。Reducer 是一个纯 JavaScript 函数,用于处理 Action 并返回更新后的应用程序状态。

通过 Store、Action 和 Reducer,我们可以实现管理复杂状态的应用程序。

1.2 示例

下面是一个简单的 Redux 示例:

import { createStore } from 'redux'

const reducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

const store = createStore(reducer)

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

store.dispatch({ type: 'INCREMENT' })
store.dispatch({ type: 'INCREMENT' })
store.dispatch({ type: 'DECREMENT' })

在上面的示例中,首先我们创建了一个 reducer,它的作用是接受当前应用程序的状态和分发的 Action,并返回新的状态。在 reducer 中,我们定义了两种 Action:INCREMENT 和 DECREMENT。当我们分发 INCREMENT 和 DECREMENT Action 时,reducer 会根据 Action 的 type 属性更新应用程序的状态。

接着,我们创建了一个 Store,并传入了之前定义好的 reducer。通过 Store.dispatch 方法,我们分发了三次 Action,并每次触发了 Store.subscribe 方法,输出了 Store 的当前状态。

最后运行代码,可以得到以下输出:

1.3 安装

在使用 Redux 之前,我们需要先安装它。可以通过 npm 来安装 Redux:

2. Redux 核心概念

2.1 Store

Store 是 Redux 中的核心概念。它存储了所有的应用程序状态,并提供了一些用于管理状态的方法。在 Redux 中,Store 中的所有状态都是只读的,唯一的改变方式是分发 Action。

在 Redux 中,Store 是通过 createStore 函数创建的。createStore 函数接受一个 reducer,用于处理 Action 并返回新的状态。下面是一个简单的 createStore 示例:

import { createStore } from 'redux'

const reducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

const store = createStore(reducer)

在上面的代码中,我们首先定义了一个 reducer,用于处理 Action 并返回新的应用程序状态。然后,我们利用这个 reducer 创建了一个 Store,并把它存储在变量 store 中。

2.2 Action

在 Redux 中,Action 是应用程序的状态变化方式。Action 本质上是一个具有 type 属性的纯 JavaScript 对象。当需要改变应用程序状态时,我们只需要分发一个 Action,Redux 将自动触发 Store 更新应用程序的状态。

下面是一个例子:

store.dispatch({
  type: 'INCREMENT'
})

在上面的代码中,我们通过 store.dispatch 方法分发了一个 Action,它的 type 属性是 INCREMENT。当 Store 接收到 Action 后,会调用之前定义的 reducer 函数,并根据返回的新状态更新应用程序的状态。

2.3 Reducer

Reducer 是一个纯 JavaScript 函数,用于处理 Action 并返回新的应用程序状态。在 Redux 中,Reducer 是单向的,它不会改变传递给它的任何参数。Reducer 只要接受两个参数:原始状态(或当前状态)和 Action。它应该返回一个新的状态,不会改变原始状态。

在 Redux 中,Reducer 应该是一个纯 JavaScript 函数。这意味着,它不应该有任何副作用,例如修改输入或全局变量、请求网络等等。它应该只是一个纯粹的函数,它只依赖于传递给它的参数。

下面是一个简单的 reducer 实现:

const reducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

在上面的例子中,我们定义了一个 reducer 函数,它接受两个参数 state 和 action。在 reducer 函数中,我们使用 switch 映射所有可能的 Action,而不需要使用 if 语句。当 reducer 函数接收到一个 Action 时,它将根据 Action 的 type 属性更新应用程序的状态,并返回新的状态值。

2.4 combineReducers

在 Redux 中,combineReducers 是一个用于将由多个 reducer 组成的状态合并成单一状态树的辅助函数。combineReducers 接受一个对象作为参数,该对象包含多个 reducer,每个 reducer 用于处理自己的一部分状态。

下面是一个 combineReducers 的示例:

import { combineReducers, createStore } from 'redux'

const todoReducer = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, { id: action.id, text: action.text }]
    case 'REMOVE_TODO':
      return state.filter(todo => todo.id !== action.id)
    default:
      return state
  }
}

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

const rootReducer = combineReducers({
  todos: todoReducer,
  visibilityFilter: visibilityFilterReducer
})

const store = createStore(rootReducer)

在上面的代码中,我们首先定义了两个 reducer,用于处理两种不同的状态:todoReducer 和 visibilityFilterReducer。然后,我们使用 combineReducers 函数将它们组合起来,并返回一个新的 reducer(rootReducer)。在最后一行,我们使用这个 rootReducer 创建了 Store。

最后的 Store 的状态结构如下:

{
  todos: [],
  visibilityFilter: 'SHOW_ALL'
}

3. React Redux

React Redux 是一个用于将 Redux 与 React 框架相结合的库。它提供了一些帮助 React 应用程序与 Redux 进行集成的组件,例如 Provider 和 connect。

3.1 Provider

Provider 是 React Redux 提供的一个跨组件的组件。它接受一个名为 store 的属性,用于传递 Redux 的 Store 实例。Provider 的作用是让子组件能够访问到 Store。

下面是一个 Provider 的示例:

import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'

import App from './App'
import rootReducer from './reducers'

const store = createStore(rootReducer)

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

在上面的代码中,我们首先使用 createStore 函数创建了一个 Store,然后将它传递到 Provider 组件中。在 Provider 的子组件中,我们可以通过 connect 函数来连接 Store 和组件。

3.2 connect

connect 函数是 React Redux 提供的一个函数,用于将 React 组件与 Redux 的 Store 进行连接。connect 函数接受两个参数:mapStateToProps 和 mapDispatchToProps。

mapStateToProps 函数用于将 Redux 的 Store 的部分状态映射到 React 的 Props 对象中。mapDispatchToProps 函数用于将 Redux 的 ActionCreator 函数映射到 React 的 Props 对象中。

下面是一个 connect 函数的示例:

import React from 'react'
import { connect } from 'react-redux'

const Counter = ({ counter, increment, decrement }) => (
  <div>
    <h1>{counter}</h1>
    <button onClick={increment}>+</button>
    <button onClick={decrement}>-</button>
  </div>
)

const mapStateToProps = state => ({
  counter: state
})

const mapDispatchToProps = dispatch => ({
  increment: () => dispatch({ type: 'INCREMENT' }),
  decrement: () => dispatch({ type: 'DECREMENT' })
})

export default connect(mapStateToProps, mapDispatchToProps)(Counter)

在上面的代码中,我们首先定义了一个 Counter 组件,它接受 counter、increment 和 decrement 三个 Props。然后,我们定义了两个函数 mapStateToProps 和 mapDispatchToProps,并将它们传递给 connect 函数。最后,我们将 Counter 组件导出并使用 connect 函数对其进行连接。

4. 总结

在本文中,我们详细介绍了 Redux 的核心概念:Store、Action 和 Reducer。我们还通过示例代码演示了如何使用 Redux 来进行状态管理,以及如何使用 React Redux 将 Redux 集成到 React 应用程序中。

Redux 是一个非常有用的库,可以帮助我们管理复杂的应用程序状态。虽然它可能需要一些学习和理解,但一旦掌握了它,就可以轻松地管理任何规模的应用程序状态。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a3a713add4f0e0ffbc9d49


纠错反馈