以优雅方式开发模块化React + Redux应用
2023-09-05 13:50:27
当我们开始一个新的应用的时候,有一件事情是一定要考虑清楚的,因为随着项目的增大,我们需要创建的项目结构和大小都越来越复杂,一个好的代码结构能够给我们省事不少。
本篇会以todo应用为代表进行项目文件的划分,因为每个框架问世的时候都会用todo进行展示。上图就是按角色进行代码的划分。
按照这个思维我们将我们的项目进行代码划分,内容如下:
- actions.js:包含所有action创建函数,由
redux
调用 - reducers.js:包含所有reducer函数,由
redux
调用 - store.js:包含创建仓库的函数,由
redux
调用 - components:存放所有应用组件
- containers:存放业务组件
- helpers:存放各种帮助方法
- index.js:引入所有文件并启动应用
- package.json:项目配置信息
- .gitignore:git忽略文件配置
整个项目就是由这么几个文件组成。下面我们以创建todo应用为例,对上述文件进行详细讲解。
首先我们先看一下actions.js
export const ADD_TODO = 'ADD_TODO'
export const addTodo = (text) => {
return {
type: ADD_TODO,
text
}
}
这个文件里面定义了一个 action 创建函数 addTodo
,它会返回一个对象,这个对象包含一个 type
属性和一个 text
属性。
接下来看一下reducers.js
import { ADD_TODO } from './actions'
const initialState = {
todos: []
}
export const todoReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, action.text]
}
default:
return state
}
}
这个文件里面定义了一个 reducer 函数 todoReducer
,它会接收一个 state 和一个 action,然后返回一个新的 state。在这个 reducer 函数里面,我们只处理了 ADD_TODO
这个 action,当接收到这个 action 时,我们会在 state 的 todos
数组中添加一个新的元素。
再看一下store.js
import { createStore } from 'redux'
import { todoReducer } from './reducers'
const store = createStore(todoReducer)
export default store
这个文件里面定义了一个创建仓库的函数,它会接收一个 reducer 函数并返回一个仓库。
然后我们看一下components文件夹,这个文件夹里面存放着所有应用组件。
import React from 'react'
const Todo = (props) => {
return (
<li>
{props.text}
</li>
)
}
export default Todo
这个文件里面定义了一个组件 Todo
,它会渲染一个待办事项。
import React from 'react'
const TodoList = (props) => {
return (
<ul>
{props.todos.map((todo, index) => <Todo key={index} text={todo} />)}
</ul>
)
}
export default TodoList
这个文件里面定义了一个组件 TodoList
,它会渲染一个待办事项列表。
import React from 'react'
const AddTodo = (props) => {
return (
<form onSubmit={props.onSubmit}>
<input type="text" onChange={props.onChange} />
<button type="submit">添加</button>
</form>
)
}
export default AddTodo
这个文件里面定义了一个组件 AddTodo
,它会渲染一个添加待办事项的表单。
最后看一下containers文件夹,这个文件夹里面存放着业务组件。
import React, { useState } from 'react'
import { connect } from 'react-redux'
import { addTodo } from '../actions'
import AddTodo from '../components/AddTodo'
import TodoList from '../components/TodoList'
const App = (props) => {
const [text, setText] = useState('')
const handleChange = (e) => {
setText(e.target.value)
}
const handleSubmit = (e) => {
e.preventDefault()
props.addTodo(text)
setText('')
}
return (
<div>
<h1>待办事项列表</h1>
<AddTodo onSubmit={handleSubmit} onChange={handleChange} />
<TodoList todos={props.todos} />
</div>
)
}
const mapStateToProps = (state) => {
return {
todos: state.todos
}
}
const mapDispatchToProps = {
addTodo
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
这个文件里面定义了一个业务组件 App
,它会渲染整个应用。这个组件里面使用了 react-redux
的 connect
函数,这个函数可以把仓库中的 state 和 dispatch 函数注入到组件的 props 中。
最后我们看一下index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './containers/App'
import store from './store'
ReactDOM.render(<App store={store} />, document.getElementById('root'))
这个文件里面负责引入所有文件并启动应用。
这就是一个完整的 todo 应用的代码结构,希望对大家有所帮助。