React Hooks

Hooks介绍

之前没有用hooks写react的时候,用class类组件,state在构造函数定义,然后是钩子函数。

在这里,发现用的是函数组件,useState来定义state,useEffect来初始获取接口数据,比如查询列表等等。使用hooks的目的是让函数组件具备class组件的能力。

  • React 一直都提倡使用函数组件,但是有时候需要使用 state 或者其他一些功能时,只能使用类组件,因为函数组件没有实例,没有生命周期函数,只有类组件才有。
  • Hooks 是 React 16.8 新增的特性,React Hooks 就是让你不必写class组件就可以用state和其他的React特性;
  • 如果你在编写函数组件并意识到需要向其添加一些 state,以前的做法是必须将其它转化为 class。现在你可以直接在现有的函数组件中使用 Hooks
  • 凡是 use 开头的 React API 都是 Hooks

这里useState比原来的setstate感觉方便一点。在这里,没有super(props),没有this,没有生命周期。hooks其实就是对原有React 的 API 进行了封装,暴露比较方便使用的钩子。

 

常用hook

useState 初始化和设置状态 。会返回一个数组:一个 state,一个更新 state 的函数。

const [isEdit, setEdit] = useState(false);
  • 在初始化渲染期间,返回的状态 (state) 与传入的第一个参数 (initialState) 值相同
  • 你可以在事件处理函数中或其他一些地方调用这个函数。它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并,而是直接替换

useEffect  componentDidMount,componentDidUpdate和componentWillUnmount和结合体,所以可以监听useState定义值的变化 监听变化 。会在第一次渲染之后和每次更新之后都会执行。

useEffect(() => {            getList();    }, [fresh]);

fresh 改变,就会调用getList()。

import React, { useState, useEffect } from 'react';import axios from 'axios';function App() {  const [data, setData] = useState({ hits: [] });  useEffect(async () => {    const result = await axios(      'http://localhost/api/v1/search?query=redux',    );    setData(result.data);  });  return (    <ul>      {data.hits.map(item => (        <li key={item.objectID}>          <a href={item.url}>{item.title}</a>        </li>      ))}    </ul>  );}export default App;

在useEffect中,不仅会请求后端的数据,还会通过调用setData来更新本地的状态,这样会触发view的更新。

useEffect在组件mount时执行,但也会在组件更新时执行。因为我们在每次请求数据之后都会设置本地的状态,所以组件会更新,因此useEffect会再次执行,因此出现了无限循环的情况。我们只想在组件mount时请求数据。我们可以传递一个空数组作为useEffect的第二个参数,这样就能避免在组件更新执行useEffect,只会在组件mount时执行。就是图一里面的使用方法。

useCallback  记忆作用,共有两个参数,第一个参数为一个匿名函数,就是我们想要创建的函数体。第二参数为一个数组,里面的每一项是用来判断是否需要重新创建函数体的变量,如果传入的变量值保持不变,返回记忆结果。如果任何一项改变,则返回新的结果。

const submit = useCallback(() => {  validateFields((err, values) => {    if (err) {      console.log(err);      return message.info("请完整填写表单");    } else {      onOk({ vmData, userId: values.userId });    }  });}, []);

useMemo 和useCallback就是解决性能问题的杀手锏。

useCallback和useMemo的参数跟useEffect一致,他们之间最大的区别有是useEffect会用于处理副作用,而前两个hooks不能。

useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数。

他们的作用,就是类似生命周期中的shouldComponentUpdate,当变量改变,去判断是否重新渲染。

知道useCallback有什么样的特点,那有什么作用呢?

使用场景是:有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新。

不仅是上面的例子,所有依赖本地状态或props来创建函数,需要使用到缓存函数的地方,都是useCallback的应用场景。

useContext  定义一个全局的对象,类似 context 

useReducer 可以增强函数提供类似 Redux 的功能

useMemo作用和传入参数与 useCallback 一致,useCallback返回函数,useDemo 返回值

useRef  获取 ref 属性对应的 dom

前面三个用的比较多。另外,useEffect、useMemo、useCallback都是自带闭包的。也就是说,每一次组件的渲染,其都会捕获当前组件函数上下文中的状态(state, props),所以每一次这三种hooks的执行,反映的也都是当前的状态,你无法使用它们来捕获上一次的状态。对于这种情况,我们应该使用ref来访问。

 

注意

  • 只能在顶层调用 Hook,不要在循环、条件或嵌套函数中调用 Hook。
  • 仅从 React 函数式组件中调用 Hook。不要从常规 JavaScript 函数调用 Hook。(还有另一个有效的地方来调用 Hook,即你的自定义 Hook。)

 

举个栗子

import React, { Fragment, useState, useEffect } from 'react';import axios from 'axios';function App() {  const [data, setData] = useState({ hits: [] });  const [query, setQuery] = useState('redux');  const [url, setUrl] = useState(    'http://localhost/api/v1/search?query=redux',  );  const [isLoading, setIsLoading] = useState(false);  const [isError, setIsError] = useState(false);  useEffect(() => {    const fetchData = async () => {      setIsError(false);      setIsLoading(true);      try {        const result = await axios(url);        setData(result.data);      } catch (error) {        setIsError(true);      }      setIsLoading(false);    };    fetchData();  }, [url]);  return (    <Fragment>      <input        type="text"        value={query}        onChange={event => setQuery(event.target.value)}      />      <button        type="button"        onClick={() =>          setUrl(`http://localhost/api/v1/search?query=${query}`)        }      >        Search      </button>      {isError && <div>Something went wrong ...</div>}      {isLoading ? (        <div>Loading ...</div>      ) : (        <ul>          {data.hits.map(item => (            <li key={item.objectID}>              <a href={item.url}>{item.title}</a>            </li>          ))}        </ul>      )}    </Fragment>  );}export default App;

在useEffect中,请求数据前将loading置为true,在请求完成后,将loading置为false。我们可以看到useEffect的依赖数据中并没有添加loading,这是因为,我们不需要再loading变更时重新调用useEffect。请记住:只有某个变量更新后,需要重新执行useEffect的情况,才需要将该变量添加到useEffect的依赖数组中。

loading处理完成后,还需要处理错误,这里的逻辑是一样的,使用useState来创建一个新的state,然后在useEffect中特定的位置来更新这个state。由于我们使用了async/await,可以使用一个大大的try-catch。

每次useEffect执行时,将会重置error;在出现错误的时候,将error置为true;在正常请求完成后,将error置为false。

阿里的umi HOOKs

https://hooks.umijs.org/zh-CN/hooks/life-cycle/use-mount

这个就感觉还蛮厉害的,但是得慎用。

用不好,一堆副作用,维护很麻烦!

来源:https://www.icode9.com/content-4-838651.html

(0)

相关推荐

  • 实现 React Hooks

    UI 开发有两个问题: 展示复用 逻辑复用 展示复用目前基本使用组件化来解决,逻辑复用一直以来都没有特别好的解决方案.React 从一开始的 mixin ,到 高阶组件 以及 Render Props ...

  • ReactHook快速上车

    React16.8开始内置了10个Hook,核心是2个: 状态管理:useState 副作用管理:useEffect 有状态的函数 useState 有状态组件写法: class Example ex ...

  • 深入理解 React useLayoutEffect 和 useEffect 的执行时机

    我们先看下 React 官方文档对这两个 hook 的介绍,建立个整体认识 useEffect(create, deps): 该 Hook 接收一个包含命令式.且可能有副作用代码的函数.在函数组件主体 ...

  • 简单的 useState 实现

    简单的 useState 实现 本文写于 2020 年 10 月 21 日 以下是一段非常简单的 React 代码: const App = () => { const [n, setN] = ...

  • Svelte 码半功倍

    你未注意到的最重要的指标. 注意:原文发表于2019-04-20,随着框架不断演进,部分内容可能已不适用. 所有代码都有 BUG,你写的越多,BUG 越多,这很合情合理. 同时,写的越多,费时越多,留 ...

  • React实战教程之从零开始手把手教你使用 React 最新特性Hooks API 打造一款计算机知识测验App

    前言 React 框架的优雅不言而喻,组件化的编程思想使得React框架开发的项目代码简洁,易懂,但早期 React 类组件的写法略显繁琐.React Hooks 是 React 16.8 发布以来最 ...

  • React 整体感知

    当我们由浅入深地认知一样新事物的时候,往往需要遵循 Why > What > How 这样一个认知过程.它们是相辅相成.缺一不可的.而了解了具体的 What 和 How 之后,往往能够更加 ...

  • 一切前端概念,都是纸老虎

    (给前端大学加星标,提升前端技能.) 作者:姜小抖 https://zhuanlan.zhihu.com/p/53599723 这篇文章试着聊明白这一堆看起来挺复杂的东西.在聊之前,大家要始终记得一句 ...

  • React Ref 其实是这样的

    ref 的由来 在典型的 React 数据流中,props 是父组件与子组件交互的唯一方式.要修改一个子组件,你需要使用新的 props 来重新渲染它.但是,在某些情况下,你需要在典型数据流之外强制修 ...

  • 当设计模式遇上 Hooks

    一  前言 「设计模式」是一个老生常谈的话题,但更多是集中在面向对象语言领域,如 C++,Java 等.前端领域对于设计模式的探讨热度并不是很高,很多人觉得对于 JavaScript 这种典型的面向过 ...