介绍
useReducer Hook 是 React 提供的一个 Hook,它接收一个 reducer 函数和初始 state,返回当前的 state 以及一个 dispatch
方法,可以用来更新 state。它可以用来替代 class 组件中的 state
和 setState
方法,使得代码更加简洁,更容易维护。
语法
useReducer
Hook接受两个参数。
useReducer(<reducer>,<initialState>)
reducer
函数包含您的自定义状态逻辑,initialState
可以是一个简单的值,但通常会包含一个对象。
useReducer
Hook 返回当前状态和 dispatch
方法。
示例
这是一个使用 useReducer 在待办事项应用中的示例:
- TodoList.js
import { useState } from 'react';
export default function TaskList({
todos,
onChangeTodo,
onDeleteTodo
}) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
<Task
todo={todo}
onChange={onChangeTodo}
onDelete={onDeleteTodo}
/>
</li>
))}
</ul>
);
}
function Task({ todo, onChange, onDelete }) {
const [isEditing, setIsEditing] = useState(false);
let todoContent;
if (isEditing) {
todoContent = (
<>
<input
value={todo.title}
onChange={e => {
onChange({
...todo,
title: e.target.value
});
}} />
<button onClick={() => setIsEditing(false)}>
保存
</button>
</>
);
} else {
todoContent = (
<>
{todo.title}
<button onClick={() => setIsEditing(true)}>
编辑
</button>
</>
);
}
return (
<label>
<input
type="checkbox"
checked={todo.done}
onChange={e => {
onChange({
...todo,
done: e.target.checked
});
}}
/>
{todoContent}
<button onClick={() => onDelete(todo.id)}>
删除
</button>
</label>
);
}
上述代码很简单,其中:
TaskList
组件是一个函数组件,它接收一个todos
数组,以及onChangeTodo
和onDeleteTodo
函数作为参数。TaskList
组件使用todos数组渲染一个ul
元素,其中每个todo
都会被渲染为一个 Task 组件。Task
组件是一个函数组件,它接收一个todo
对象,以及onChange
和onDelete
函数作为参数。Task
组件使用todo
对象渲染一个label
元素,其中包含一个checkbox
,用于更改todo
的状态,以及“删除”按钮,用于删除todo。
- AddTodo.js
import { useState } from 'react';
export default function AddTodo({ onAddTodo }) {
const [title, setTitle] = useState('');
return (
<>
<input
placeholder="添加待办事项"
value={title}
onChange={e => setTitle(e.target.value)}
/>
<button onClick={() => {
setTitle('');
onAddTodo(title);
}}>添加</button>
</>
)
}
上述代码主要做了三件事情:
- 我们使用
useState
Hook 来创建一个title
状态,并使用setTitle
函数来更新它。 - 渲染一个输入,它的值是
title
状态,并且当用户输入时,它会调用setTitle函数来更新 title 状态。 - 渲染 “添加” 按钮,当用户点击时,它会调用
onAddTodo
函数,并将title
状态作为参数传递给它,然后将title
状态重置为空字符串。
- index.js
import { useReducer } from 'react';
import AddTodo from './AddTodo';
import TodoList from './TodoList';
const initialTodos = [
{ id: 0, title: 'Buy milk', done: true },
{ id: 1, title: 'Eat tacos', done: false },
{ id: 2, title: 'Brew tea', done: false },
];
let nextId = 3;
function App() {
const [todos, dispatch] = useReducer(
todoReducer,
initialTodos
);
function handleAddTodo(title) {
dispatch({
type: 'added',
id: nextId++,
title: title,
});
}
function handleChangeTodo(todo) {
dispatch({
type: 'changed',
todo: todo
});
}
function handleDeleteTodo(taskId) {
dispatch({
type: 'deleted',
id: taskId
});
}
return (
<>
<AddTodo
onAddTodo={handleAddTodo}
/>
<TodoList
todos={todos}
onChangeTodo={handleChangeTodo}
onDeleteTodo={handleDeleteTodo}
/>
</>
);
}
function todoReducer(todos, action) {
switch (action.type) {
case 'added': {
return [...todos, {
id: action.id,
title: action.title,
done: false
}];
}
case 'changed': {
return todos.map(t => {
if (t.id === action.todo.id) {
return action.todo;
} else {
return t;
}
});
}
case 'deleted': {
return todos.filter(t => t.id !== action.id);
}
default: {
throw Error('Unknown action: ' + action.type);
}
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Todos />);
todoReducer
函数接收两个参数:todos
和action
。todos
是一个数组,包含所有的todo
项,action
是一个对象,包含要执行的操作的类型和其他可能需要的数据。- 根据
action.type
的值,todoReducer
函数会执行不同的操作: - 如果
action.type
的值为added
,则会添加一个新的todo
项到todos
数组中; - 如果
action.type
的值为changed
,则会更新todos
数组中指定的todo
项; - 如果
action.type
的值为deleted
,则会从todos
数组中删除指定的todo
项。 - 最后,todoReducer函数会返回一个新的todos数组,其中包含所有的更新后的todo项。
useReducer
Hook 是在React应用程序中管理状态的一个很好的方法。它比 useState
Hook 更强大,允许更复杂的状态逻辑。
评论 (0)