内容简介:原文地址:React v16.7.0-alpha 引入了
原文地址: How to Build a Todo List with React Hooks
React v16.7.0-alpha 引入了 钩子(Hooks) 。开心!
什么是钩子(Hooks)?
钩子是能让你在没有用es6类的情况下使用React的状态, 生命周期钩子这些特性的功能。
优势:
- 隔离状态相关逻辑,使测试更加容易
- 不需要使用渲染属性或者高阶组件就可以共享状态相关逻辑
- 根据逻辑而不是生命周期钩子来分离应用程序的关注点
- 避免ES6类,因为它们很奇怪,不是真正的类,甚至会误导有经验的JavaScript开发人员
查看更多: React’s official Hooks intro
不要在生产环境使用
写这篇文章时,钩子还处于内部测试(alpha)阶段。它们的API随时都可能改变。
我建议你在你的业余项目中体验钩子,在它们成为稳定版本之前,不要在线上代码中使用。
构建事项列表
待办事项清单是使用广泛的例子,理由很充分——它们是很棒的练习工具。无论你想尝试任何语言或库我都推荐使用它。
在这个例子中,我们只实现其中的一小部分功能:
- 使用Material Design展示事项列表
- 通过input添加事项
- 删除事项
配置
这是 github 和 CodeSandbox 的地址
git clone https://github.com/yazeedb/react-hooks-todo cd react-hooks-todo npm install
master分支已经实现了这些功能,如果你想自己跟着实现,请切到start分支。
git checkout start
启动工程
npm start
这个应用应该跑在 localhost:3000 上,这是初始UI:
我们已经设置了material-ui来给页面一个专业的外观,现在我们加入更多功能!
ToDoForm 组件
添加一个新文件, src/TodoForm.js 。这是初始代码:
import React from 'react';
import TextField from '@material-ui/core/TextField';
const TodoForm = ({ saveTodo }) => {
return (
<form>
<TextField
variant="outlined"
placeholder="Add todo"
margin="normal"
/>
</form>
);
};
export default TodoForm;
通过组件名字,我们就知道它是用来添加事项的,它也就是我们的第一个钩子。
useState
看这段代码:
import { useState } from 'react';
const [value, setValue] = useState('');
useState 是一个接收初始状态(state)返回一个数组的函数。 console.log 它吧。
数组的第一个值是你的state现在的值,第二个值是state的更新方法。
所以我们把它们叫做 value 和 setValue , 并使用es6解构赋值对它们进行赋值。
对表单(Form)使用useState
我们的表单应该跟踪input的值并在保存提交时执行 saveTodo 方法。 useState 能帮我们实现它。
更新 updateForm.js , 这是更新之后的代码:
import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
const TodoForm = ({ saveTodo }) => {
<b>const [value, setValue] = useState('');</b>
return (
<form
<strong>onSubmit={event => {</strong>
event.preventDefault();
saveTodo(value);
}}
>
<TextField
variant="outlined"
placeholder="Add todo"
margin="normal"
onChange={event => {
setValue(event.target.value);
}}
value={value}
/>
</form>
);
};
export default TodoForm;
回到 index.js ,引入并且使用这个组件。
...
import TodoForm from './TodoForm';
...
const App = () => {
return (
<div className="App">
<Typography component="h1" variant="h2">
Todos
</Typography>
<TodoForm saveTodo={console.warn} />
</div>
);
};
现在你在input输入的值已经可以被打印出来了。(记得敲enter哦)
对事项列表(todos)使用useState
我们的事项列表todos也需要state。在 index.js 中引入 useState 。初始state应该是空数组。
import React, { useState } from 'react';
...
const App = () => {
const [todos, setTodos] = useState([]);
return ...
TodoList组件
建立一个新文件: src/TodoList.js
大部分代码是来自Material-UI库的高级组件, 这是更新之后的代码:
import React from 'react';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
import ListItemText from '@material-ui/core/ListItemText';
import Checkbox from '@material-ui/core/Checkbox';
import IconButton from '@material-ui/core/IconButton';
import DeleteIcon from '@material-ui/icons/Delete';
const TodoList = ({ todos, deleteTodo }) => (
<List>
{todos.map((todo, index) => (
<ListItem key={index.toString()} dense button>
<Checkbox tabIndex={-1} disableRipple />
<ListItemText primary={todo} />
<ListItemSecondaryAction>
<IconButton
aria-label="Delete"
onClick={() => {
deleteTodo(index);
}}
>
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
);
export default TodoList;
它接收两个属性:
- todos: 事项数组,我们遍历数组,建立每一个事项
- deleteTodo: 点击一个事项的删除按钮触发这个方法,它接收一个参数: 索引,这个索引唯一标识每一个事项。
在 index.js 中引入这个组件。
...
import TodoList from './TodoList';
import './styles.css';
const App = () => { ...
并在 App 方法中使用它:
...
<TodoForm saveTodo={console.warn} />
<TodoList todos={todos} />
添加事项
还是在 index.js 中,编辑 TodoForm 的属性, saveTodo :
<TodoForm
saveTodo={todoText => {
const trimmedText = todoText.trim();
if (trimmedText.length > 0) {
setTodos([...todos, trimmedText]);
}
}}
/>
这里我们只是把空格去掉,把新的值添加到 todos 中。
我们现在可以添加事项了!
清除input框
现在添加新的事项后,我们没有把input清空,这是不好的用户体验!
我们只需要在 TodoForm.js 中做一点小改动,就可以修复它。
<form
onSubmit={event => {
event.preventDefault();
saveTodo(value);
setValue('');
}}
>
当事项被保存后,我们就把form的state变成空字符串。
现在看起来很好了!
删除事项
TodoList 为每一条事项都提供了索引,根据索引我们能找到我们想删除的事项。
// TodoList.js
<IconButton
aria-label="Delete"
onClick={() => {
deleteTodo(index);
}}
>
<DeleteIcon />
</IconButton>
在 index.js 中传递这个函数
<TodoList
todos={todos}
deleteTodo={todoIndex => {
const newTodos = todos
.filter((_, index) => index !== todoIndex);
setTodos(newTodos);
}}
/>
我们使用 setTodos 方法把所有不符合 index 的事项保存下来。
删除功能完成!
抽取事项列表(todos)的useState
文章开头我提到 钩子便于分离状态和组件的逻辑。所以我们在这个应用中可以这样做。
新建一个文件叫 src/useTodoState.js
import { useState } from 'react';
export default initialValue => {
const [todos, setTodos] = useState(initialValue);
return {
todos,
addTodo: todoText => {
setTodos([...todos, todoText]);
},
deleteTodo: todoIndex => {
const newTodos = todos
.filter((_, index) => index !== todoIndex);
setTodos(newTodos);
}
};
};
这就是 index.js 中原来的代码,我们只是把它分离出来了!我们的状态处理逻辑不再和组件混在一起了!
现在我们只需要引入它,这是更新之后的代码:
import React from 'react';
import ReactDOM from 'react-dom';
import Typography from '@material-ui/core/Typography';
import TodoForm from './TodoForm';
import TodoList from './TodoList';
import useTodoState from './useTodoState';
import './styles.css';
const App = () => {
const { todos, addTodo, deleteTodo } = useTodoState([]);
return (
<div className="App">
<Typography component="h1" variant="h2">
Todos
</Typography>
<TodoForm
saveTodo={todoText => {
const trimmedText = todoText.trim();
if (trimmedText.length > 0) {
addTodo(trimmedText);
}
}}
/>
<TodoList todos={todos} deleteTodo={deleteTodo} />
</div>
);
};
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
现在一切工作正常!
抽取表单input中的useState
我们可以对表单做同样的处理!
新建一个文件: src/useInputState.js
import { useState } from 'react';
export default initialValue => {
const [value, setValue] = useState(initialValue);
return {
value,
onChange: event => {
setValue(event.target.value);
},
reset: () => setValue('')
};
};
现在 todoForm.js 应该变成这样:
import React from 'react';
import TextField from '@material-ui/core/TextField';
import useInputState from './useInputState';
const TodoForm = ({ saveTodo }) => {
const { value, reset, onChange } = useInputState('');
return (
<form
onSubmit={event => {
event.preventDefault();
saveTodo(value);
reset();
}}
>
<TextField
variant="outlined"
placeholder="Add todo"
margin="normal"
onChange={onChange}
value={value}
/>
</form>
);
};
export default TodoForm;
现在我们全部完成了!
希望你喜欢!!
谢谢!
作者: Yazeed Bzadough
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 产品待办事项列表梳理 Product Backlog Grooming
- 微软待办事项To-Do Windows 10 UWP版更新:支持多账户切换
- 禅道 9.8.stable 发布,增强待办功能和消息通知功能
- 喧喧 1.5.0 优化服务器性能,支持将消息创建为然之待办
- [ Laravel从入门到精通 ] 测试系列 —— 通过测试驱动开发构建待办任务项目(一):后端 API 接口篇
- [ Laravel从入门到精通 ] 测试系列 —— 通过测试驱动开发构建待办任务项目(二):前端功能和浏览器...
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
群智能优化算法及其应用
雷秀娟 / 2012-8 / 85.00元
《群智能优化算法及其应用》编著者雷秀娟。 《群智能优化算法及其应用》内容提要:本书以群智能优化算法中的粒子群优化(]Particle Swarm Optimization,PSO)算法为主线,着重阐述了PSO算法的基本原理、改进策略,从解空间设计、粒子编码以及求解流程等方面进行了详细设计与阐述,对蚁群优化(Ant Colony Optimization,AC0)算法、人工鱼群(Art......一起来看看 《群智能优化算法及其应用》 这本书的介绍吧!