📜  讨论Redux(1)

📅  最后修改于: 2023-12-03 15:12:06.465000             🧑  作者: Mango

讨论 Redux

什么是 Redux?

Redux 是一个可预测性状态容器,用于 JavaScript 应用程序的状态管理。它使得应用程序和 UI 的状态变化变得容易追踪和调试。

Redux 的工作原理非常简单:应用程序的所有状态都被存储在一个单一的状态树中,并通过操作这个状态树来更新应用程序的状态。这个状态树是只读的,因此修改它的唯一方式是通过派发一个 action(一个包含所需更新的状态信息的普通 JavaScript 对象)。

Redux 还提供了一个中间件机制,使得可以对 action 进行异步处理、记录日志、路由以及其他逻辑,这就使得应用程序更加高效和可维护。

Redux 的主要概念

Redux 的设计被组织在三个核心概念之上:

Store

Store 是 Redux 中存储应用程序状态的单一对象。这个对象包含了整个应用程序的状态树。Store 可以被视为应用程序的唯一源。它允许应用程序的组件订阅状态变化,并提供了一种途径通过 dispatching actions 来更新状态。

Action

Action 是负责连接应用程序的组件和状态树的机制。它是描述性质的纯粹 JavaScript 对象,包含了一个操作类型和负荷数据(比如用户输入、服务端状态更新等等)。当应用程序的状态发生变化时,Redux 会通过 dispatching actions 来更新状态。

Reducer

Reducer 是一个纯函数,它接受先前的状态以及计算后的 action,返回一些新的状态。这个函数是 Redux 中更新状态的枢纽。Reducers应该是无副作用的,这意味着应该仅仅依靠状态树在计算状态的过程中进行计算,而不是通过副作用对外部状态进行更改。

Redux 在实践中的运用

在实践中,Redux 首先会和 React 一起使用,以实现一个可逆转的应用程序架构。在 React + Redux 的组合中,应用程序状态被存储在 Redux Store 中,并由 React 组件来使用。当组件需要更新应用程序的状态时,它会派发一个 action,这个 action 由 Redux 处理。由 Redux 处理后,新的应用程序状态被存储在 Store 中,React 组件会以此来更新自己的状态,从而实现了应用程序状态的同步。

安装 Redux

可以通过 npm 下载 Redux ,并使用 WebPack 或者 webpack-dev-server 来设置开发环境。以下是 Redux 的安装方式:

npm install --save redux
npm install --save-dev webpack webpack-dev-server babel-loader babel-core babel-preset-es2015 babel-preset-react
创建 Store

要创建一个 Redux 的 Store,我们需要先定义一个 reducer,然后使用 createStore 函数来创建应用程序的 Store:

import { createStore } from 'redux';

const initialState = {
    todos: []
}

function rootReducer(state = initialState, action) {
    switch(action.type) {
        case 'ADD_TODO':
            return {
                ...state,
                todos: [...state.todos, action.payload]
            }
        case 'REMOVE_TODO':
            return {
                ...state,
                todos: state.todos.filter(todo => todo.id !== action.id)
            }
        default:
            return state;
    }
}

const store = createStore(rootReducer);

在上面的代码中,我们通过 createStore 函数创建了一个 Store,然后将我们的 rootReducer 函数传递给 createStore 函数(rootReducer 函数是一个纯函数,需要给它传递先前的状态和 action 来计算新的状态)。我们还定义了初始状态 initialState 和 reducer 函数,它们对应整个应用程序的状态树和状态更新。

创建 Action

为了更新 Redux 的 Store,我们需要先创建一个 action。Action 是一个普通的 JS 对象,它必须包含一个 type 属性(代表 action 类型),以及可选的 payload 属性(代表要更新的负荷数据)。一般来说,我们会将 action 创建函数放在单独的文件中:

export const ADD_TODO = 'ADD_TODO';
export const REMOVE_TODO = 'REMOVE_TODO';

let nextTodoId = 0;

// Action Creator
export function addTodo (text) {
    return {
        type: ADD_TODO,
        payload: {
            id: ++nextTodoId,
            text
        }
    }
}

export function removeTodo (id) {
    return {
        type: REMOVE_TODO,
        payload: id
    }
}

在上面的代码中,我们定义了两个 action 类型,ADD_TODO 和 REMOVE_TODO,以及对应的 action 创建函数 addTodo 和 removeTodo。当我们需要更新 Store 时,我们只需要调用对应的 action 创建函数即可。

连接 React 和 Redux

现在,我们需要将 Redux 和 React 连接起来,以使其同步更新应用程序的状态。为此,我们可以使用两个工具:connect 和 Provider。

我们需要从 react-redux 包中使用 connect 函数,connect 函数会将 Redux State 对象转换为 React 组件的 props 对象,使得我们可以轻松地更新应用程序的状态。我们还需要使用 Provider 组件来将 React 应用程序和 Redux Store 连接在一起。Provider 组件通过将应用程序的 Store 作为 props 传递给组件,使得所有的组件都可以访问 Store。

下面是一个简单的例子,它演示了如何在 React 中使用 Redux:

import React from 'react';
import { connect } from 'react-redux';
import { addTodo, removeTodo } from './actions';

class TodoList extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            text: ''
        };
    }

    handleTodoInput = event => {
        this.setState({ text: event.target.value })
    };

    handleAddTodo = () => {
        if (this.state.text) {
            this.props.addTodo(this.state.text);
            this.setState({ text: '' });
        }
    }

    handleRemoveTodo = id => {
        this.props.removeTodo(id);
    }

    render() {
        return (
            <div>
                <h2>Todo List</h2>
                <input type="text" value={this.state.text} onChange={this.handleTodoInput} />
                <button onClick={this.handleAddTodo}>Add Todo</button>
                <ul>
                    {this.props.todos.map(todo => (
                        <li key={todo.id}>
                            {todo.text} <button onClick={() => this.handleRemoveTodo(todo.id)}>X</button>
                        </li>
                    ))}
                </ul>
            </div>
        )
    }
}

const mapStateToProps = state => ({
    todos: state.todos
});

const mapDispatchToProps = {
    addTodo,
    removeTodo
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoList);

在上面的代码中,我们定义了一个 TodoList 组件,它包含一个输入框、一个添加按钮,以及一个待办清单。当我们添加一个新的待办事项时,我们会派发一个 ADD_TODO action。当我们点击待办事项的删除按钮时,我们会派发一个 REMOVE_TODO action。我们通过 connect 函数将 TodoList 组件连接到 Store、将 redux state 映射到组件的 props 上、将 action dispatch 映射到组件的 props 上。最后,我们导出这个被 connect 包装过的组件。

结论

Redux 是一个非常有用的状态容器,它可以用于管理 JavaScript 应用程序的状态。在实践中,Redux 结合 React 使用,以实现一个可逆转的、可维护的应用程序架构。无论你是正在构建一个大型的单页面应用,还是只是简单地构建一些小型的应用程序,Redux 都是值得一试的。