前言
React 是一个由 Facebook 开发的 JavaScript 库,用于构建用户界面。Redux 是一个 JavaScript 应用程序状态管理工具,用于管理应用程序的状态。React 和 Redux 很容易集成,并且一起使用时能够让开发人员更加高效的构建 Web 应用程序。
在本篇文章中,我们将深入探讨 React 结合 Redux 的开发实践,包括基础知识、项目架构、数据流程、组件设计和最佳测试实践等方面的内容,希望能为前端开发人员提供更多有深度的指导和学习的材料。
基础知识
React
React 采用组件的形式构建 Web 应用程序的用户界面。每个具体的组件可以被认为是一个独立的模块,具有输入、输出和生命周期等特点。在每个组件内部,可以使用 JSX 和 JavaScript 来描述组件的具体内容和行为。
例如,下面是一个简单的 React 组件示例:
import React from 'react';
const HelloWorld = ({ name }) => (
<div>
Welcome, {name}!
</div>
);在这个组件中,我们使用 import 指令来引用 React 库,然后使用 const 关键字定义一个无状态函数组件 HelloWorld。该组件接受一个名为 name 的属性,然后在 div 元素内部输出 Welcome, {name}! 的内容。
当我们在应用程序中使用这个组件时,只需要像下面这样:
<HelloWorld name="React" />
就可以在页面上输出 Welcome, React! 的内容了。
Redux
Redux 是一个状态管理工具,用于存储应用程序的所有状态。Redux 的状态存储是全局的,可以在整个应用程序的各个组件中进行访问和修改。
Redux 的状态管理包括三个基本概念:actions、reducers 和 stores。
actions:代表了应用程序中的某个事件的发生,可能会改变状态。例如,用户点击按钮时,就会触发一个addTodo的action。reducers:用于根据给定的action来更新应用程序的状态。例如,当用户点击addTodo按钮时,就可以用一个reducer来添加一个新的待办事项。stores:存储了整个应用程序的状态。当应用程序状态改变时,store会通知所有的view层组件重新渲染,以确保所有的视图都与最新的应用程序状态保持同步。
项目架构
在实践中,我们可以使用 Redux 来构建一个良好的项目架构,以便更好地管理应用程序的状态。下面是一个简单的项目架构示例:
// www.javascriptcn.com code example src ├── actions │ └── todos.js ├── components │ ├── AddTodo.js │ ├── Footer.js │ ├── Todo.js │ └── TodoList.js ├── constants │ └── ActionTypes.js ├── reducers │ ├── index.js │ ├── todos.js │ └── visibilityFilter.js ├── store │ └── configureStore.js └── index.js
在这个项目架构中,我们将应用程序分为了以下几个部分:
actions:用于定义应用程序中所有的action,包括ADD_TODO、TOGGLE_TODO等等。components:用于定义应用程序中所有的组件,包括AddTodo、TodoList和Footer等等。constants:用于定义所有的常量,如ActionTypes等。reducers:用于定义所有的reducer,包括todos、visibilityFilter等等。store:用于定义整个应用程序的store。index.js:用于定义整个应用程序的入口。
数据流程
在 React + Redux 的开发实践中,我们使用以下数据流程来管理整个应用程序的状态,以确保每个状态的变化都能够被正确地重现在用户界面上。

以上图为例,用户在 TodoList 组件中点击 "Completed" 按钮,会触发 setFilter 函数调用,该函数会派发一个 SET_FILTER 的 action。然后,visibilityFilter 的 reducer 会收到该 action,并根据该 action 更新应用程序状态中的 visibilityFilter 值。最后,整个应用程序的 store 会被更新,通知所有的视图重新渲染以确保与最新的应用程序状态保持同步。
组件设计
在 React + Redux 的开发实践中,我们可以使用 containers 和 presentational components 两种不同的组件来分离业务逻辑和视图展示。
containers:负责与 Redux 交互,包括从 Redux 获取 store 中的状态和 action,然后传递给 presentational components。presentational components:仅负责通过props接收来自 containers 的数据,然后根据这些数据展示正确的视图。
例如,下面是一个 containers 与 presentational components 的组合示例:
// www.javascriptcn.com code example
// 容器组件
import { connect } from 'react-redux'
import { addTodo } from '../actions'
import AddTodo from '../components/AddTodo'
const mapDispatchToProps = dispatch => ({
onSubmit: text => dispatch(addTodo(text))
})
export default connect(null, mapDispatchToProps)(AddTodo)在这个容器组件中,我们使用 connect 方法将 React 和 Redux 进行连接,将 addTodo action 提交传递给 presentational components 中的 AddTodo 组件。
// www.javascriptcn.com code example
// 展示型组件
import React, { useState } from 'react'
const AddTodo = ({ onSubmit }) => {
const [text, setText] = useState('')
const handleSubmit = e => {
e.preventDefault()
if (!text.trim()) return
onSubmit(text)
setText('')
}
return (
<form onSubmit={handleSubmit}>
<input type="text" value={text} onChange={e => setText(e.target.value)} />
<button type="submit">Add Todo</button>
</form>
)
}
export default AddTodo在这个展示型组件中,我们只关心展示页面内容,并将 onSubmit 函数作为 props 从容器组件中接收,以便向 store 中派发一个新的 addTodo action。
通过将组件分为 containers 和 presentational components,我们可以更好地分离业务逻辑和视图展示,使得应用程序更加容易维护和测试。
最佳测试实践
在 React + Redux 的开发实践中,单元测试和集成测试都非常重要。以下是一些最佳测试实践供参考:
对于 Redux 中的
actions和reducers,可以使用 Jest 进行测试。对于
containers和presentational components,可以使用 React 的自带测试工具或者 Jest 的 snapshot 测试进行测试。对于集成测试(即测试整个应用程序),可以使用超级测试或者 E2E 测试(如 Cypress.io 或 Selenium 等)进行测试。
为了获得最佳测试效果,应该尽可能地编写可测试的代码,遵循单一职责原则并尽可能地避免副作用。
例如,在 TodoList 组件中,我们可以使用以下代码来测试组件的渲染结果是否正确:
// www.javascriptcn.com code example
import React from 'react'
import { shallow } from 'enzyme'
import TodoList from '../TodoList'
describe('TodoList component', () => {
const mockTodos = [
{ id: 1, text: 'mock todo 1', completed: false },
{ id: 2, text: 'mock todo 2', completed: true },
{ id: 3, text: 'mock todo 3', completed: false }
]
it('should render correctly', () => {
const wrapper = shallow(<TodoList todos={mockTodos} />)
expect(wrapper.find('ul').children().length).toBe(3)
})
})在这个测试代码中,我们首先使用 shallow 方法创建一个透明的 TodoList 组件,并通过 props 传递 mocks 后,验证列表数据是否渲染正确。
结语
通过本篇文章,我们深入探讨了 React + Redux 的开发实践之路,并介绍了如何在项目架构、数据流程、组件设计和最佳测试实践等方面进行更好的开发实践。希望这些内容能够为前端开发人员提供更多有深度的指导和学习的材料。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d65b1ca941bf7134c14705