Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Hook 基础篇之 useState #32

Open
QC-L opened this issue Mar 23, 2019 · 0 comments
Open

React Hook 基础篇之 useState #32

QC-L opened this issue Mar 23, 2019 · 0 comments

Comments

@QC-L
Copy link
Owner

QC-L commented Mar 23, 2019

最近一直在维护 React 中文文档,重点维护了 Hook 相关的部分,因此总结下 Hook 相关的内容以及自己的一些看法。

注:看了很多文章大家都直接使用了英文的 Hooks,这里想纠正一下,建议大家以后直接使用 Hook 即可。

Hook 简介

简单来讲,Hook 的意义:

  1. 在函数组件中可以使用 state 及 React 其他特性的一种方式,旨在复用代码逻辑;
  2. 替换掉 HOC 及 Render Props 带来的冗余代码,以及对组件结构带来的破坏性;
  3. 降低 React 学习成本,去除学习 JavaScript 中 class 带来的困扰,如函数的 this 绑定问题,不稳定语法提案,以及生命周期带来困扰;
  4. 不用再纠结用哪种组件形式,直接使用函数组件即可。

注:

  1. class 组件不会被替换掉,无需担心之前代码需要重写的问题。
  2. Hook 只能放在函数的顶层。

Hook 的简单使用

系统提供的 Hook 有以下几种:

  1. 基础 Hook
    • useEffect 为组件添加 effect 特性
    • useState 为组件添加 State 特性
    • useContext 为组件添加 Context 特性
  2. 额外 Hook
    • useReducer 类似于 Redux
    • useRef
    • useLayoutEffect
    • useImperativeHandle
    • useCallback
    • useMemo
    • useDebugValue

useState()

state 在函数组件中的使用:

const [value, setValue] = useState('');

useEffect()

简易的验证码倒计时的例子:

const [count, setCount] = useState(60);
useEffect(() => {
  let interval = setInterval(() => {
    setCount(count => count - 1);
  }, 1000);
  return () => {
	clearInterval(interval);
  };
}, []);

使用 Hook 编写 TodoList

TodoList 是大家学习新内容的首选项目,话不多说,直接开始。

环境配置

使用 create-react-app 搭建环境,并引入 ant-design

$ create-react-app react-hook-todo && cd react-hook-todo
$ yarn add antd

修改 App.js 的代码:

import React, { Component } from 'react';
import Button from 'antd/lib/button';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <Button type="primary">添加 Todo</Button>
      </div>
    );
  }
}

export default App;

修改 App.css 的样式:

@import '~antd/dist/antd.css';

.App {
  text-align: center;
}

...

开启 Todo 之旅

首先,修改下组件结构,将 App 组件改为函数式,并添加一个 Input 组件:

import React from 'react';
import Button from 'antd/lib/button';
import Input from 'antd/lib/input';
import './App.css';

function App() {
  return (
    <div className="App">
      <div className="Background">
        <Input className="my-input" style={{width: 200, marginRight: 10}} placeholder="请输入 Todo"></Input>
        <Button type="primary">添加 Todo</Button>
      </div>
    </div>
  );
}

export default App;

接下来,当输入框输完内容,点击添加 Todo,会添加一个 Todo 到列表中。因此,我们需要 state 来存储当前输入的 Todo:

import React, { useState } from 'react';

function App() {
  const [todo, setTodo] = useState('');
  return (
    <div className="App">
      <div className="Background">
        <Input value={todo} className="my-input" onChange={(e) => setTodo(e.target.value)} style={{width: 200, marginRight: 10}} placeholder="请输入 Todo"></Input>
        <Button type="primary">添加 Todo</Button>
      </div>
    </div>
  );
}  

然后,需要将每次输入的 Todo 保存在列表中,因此需要再次引入一个 TodoList 的 state。
并且每次输入完成,点击添加后,应该清除之前的 todo 的值:

function App() {
  const [todo, setTodo] = useState('');
  const [todoList, setTodoList] = useState([]);
  return (
    <div className="App">
      <div className="Background">
        <Input value={todo} className="my-input" onChange={(e) => setTodo(e.target.value)} style={{width: 200, marginRight: 10}} placeholder="请输入 Todo"></Input>
        <Button type="primary" onClick={() => setTodoList(todoList => {
          setTodo('');
          return [...todoList, todo];
        })}>添加 Todo</Button>
      </div>
    </div>
  );
}

最后,我们使用一个列表来展示所生成的 TodoList:

创建 TodoList 组件:

import React from 'react';

function TodoList(props) {
  let { list } = props;
  return (
    <div className="todo-list">
      <ul>
        {
          list.map((item, index) => {
            return <li key={index}>{item}</li>
          })
        }
      </ul>
    </div>
  );
}

export default TodoList;

引入 TodoList 组件,并传入我们生成的 todoList 的 state:

import TodoList from './components/TodoList';

function App() {
  const [todo, setTodo] = useState('');
  const [todoList, setTodoList] = useState([]);
  return (
    <div className="App">
      <div className="Background">
        <Input value={todo} className="my-input" onChange={(e) => setTodo(e.target.value)} style={{width: 200, marginRight: 10}} placeholder="请输入 Todo"></Input>
        <Button type="primary" onClick={() => setTodoList(todoList => { 
          setTodo('');
          return [...todoList, todo];
        })}>添加 Todo</Button>
      </div>
      <TodoList list={todoList}></TodoList>
    </div>
  );
}

总结

上述使用了 useState 巧妙的实现了 TodoList 的效果。总的来说,Hook 还是非常便捷的。下一节,我们将继续完善这个 TodoList,加入更多的 Hook。

参考

Hook 简介
Hook 概览
使用 State Hook

@QC-L QC-L changed the title React Hook 进阶 React Hook 深入学习之 useState Mar 31, 2019
@QC-L QC-L changed the title React Hook 深入学习之 useState React Hook 基础篇之 useState Jul 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant