📅  最后修改于: 2023-12-03 15:12:06.465000             🧑  作者: Mango
Redux 是一个可预测性状态容器,用于 JavaScript 应用程序的状态管理。它使得应用程序和 UI 的状态变化变得容易追踪和调试。
Redux 的工作原理非常简单:应用程序的所有状态都被存储在一个单一的状态树中,并通过操作这个状态树来更新应用程序的状态。这个状态树是只读的,因此修改它的唯一方式是通过派发一个 action(一个包含所需更新的状态信息的普通 JavaScript 对象)。
Redux 还提供了一个中间件机制,使得可以对 action 进行异步处理、记录日志、路由以及其他逻辑,这就使得应用程序更加高效和可维护。
Redux 的设计被组织在三个核心概念之上:
Store 是 Redux 中存储应用程序状态的单一对象。这个对象包含了整个应用程序的状态树。Store 可以被视为应用程序的唯一源。它允许应用程序的组件订阅状态变化,并提供了一种途径通过 dispatching actions 来更新状态。
Action 是负责连接应用程序的组件和状态树的机制。它是描述性质的纯粹 JavaScript 对象,包含了一个操作类型和负荷数据(比如用户输入、服务端状态更新等等)。当应用程序的状态发生变化时,Redux 会通过 dispatching actions 来更新状态。
Reducer 是一个纯函数,它接受先前的状态以及计算后的 action,返回一些新的状态。这个函数是 Redux 中更新状态的枢纽。Reducers应该是无副作用的,这意味着应该仅仅依靠状态树在计算状态的过程中进行计算,而不是通过副作用对外部状态进行更改。
在实践中,Redux 首先会和 React 一起使用,以实现一个可逆转的应用程序架构。在 React + Redux 的组合中,应用程序状态被存储在 Redux Store 中,并由 React 组件来使用。当组件需要更新应用程序的状态时,它会派发一个 action,这个 action 由 Redux 处理。由 Redux 处理后,新的应用程序状态被存储在 Store 中,React 组件会以此来更新自己的状态,从而实现了应用程序状态的同步。
可以通过 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
要创建一个 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 函数,它们对应整个应用程序的状态树和状态更新。
为了更新 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 创建函数即可。
现在,我们需要将 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 都是值得一试的。