React Hooks

React Hooks?

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

使用过React的兄弟们都知道,在React中有两种组件:函数式组件类组件。在React16.8之前,函数式组件是不能玩refstate的,就连生命周期都不能使用,最主要的原因是函数式组件没有this这个概念,而state、ref、生命周期函数等都是挂载在组件自身上。所以很多人选择使用类组件。而React16.8新增的Hooks就是为了增强函数式组件,引入了一系列的Hooks来完善函数式组件的功能。

有哪些Hooks,怎么使用?

在这里例举一些常用的Hooks,其他Hooks可以查看React中文文档

React Hooks 都以use开头,Hook 本质就是 JavaScript 函数。

1 > useState -> state hook

state是React组件的一个重要属性,用于记录状态,使用setState方法更新state和视图。

我们先看一下在类组件中如何使用state:

类组件中使用

import React, { Component } from 'react'

export default class RClassComp extends Component {

  state = {
    account: '',
    age: 0
  }

  handleClick = () => {
    this.setState({
      account: 'CoCoyY1',
      age: 18
    });
  }

  render() {
    return (
      <>
        <div>姓名:{this.state.account}</div>
        <div>年龄:{this.state.age}</div>
        <button onClick={this.handleClick}>点我</button>
      </>
    )
  }
}
复制代码

效果图:

rcc1.gif

在函数式组件中使用state:

使用useState这一个Hook可以让我们在函数式组件中使用state,useState方法接收一个初始值,返回一个数组,数组第一项为state,第二项为该state的set方法

在函数式组件中使用

import React, { useState } from 'react';

export default () => {

  const [obj, setObj] = useState({account: '', age: 0});

  const handleClick = () => {
    setObj({
      account: 'CoCoyY1',
      age: 18
    });
  }

  return (
    <>
      <div>----RFC----</div>
      <div>姓名:{obj.account}</div>
      <div>年龄:{obj.age}</div>
      <button onClick={handleClick}>点我</button>
    </>
  )
}
复制代码

效果图:

rfc1.gif

2 > useRef -> ref hook

ref属性用来准确获取一个组件或元素的节点,虽然react官方不推荐大量使用,但还是非常常用的一个属性。

在类组件中使用ref:

类组件中有三种使用ref的方式:

(1)使用字符串;

(2)使用箭头函数(本人常用);

(3)使用createRef方法; -> 此方法取值时需要取current属性;

类组件中

import React, { Component } from 'react'

export default class RClassComp extends Component {

  state = {
    account: '',
    age: 0
  }

  handleClick = () => {
    const accountValue = this.inputEl.value;
    this.setState({
      account: accountValue,
      age: 18
    });
  }

  render() {
    return (
      <>
        <div>姓名:{this.state.account}</div>
        <div>
          <input ref={c => this.inputEl = c} type="text" />
        </div>
        <div>年龄:{this.state.age}</div>
        <button onClick={this.handleClick}>点我</button>
      </>
    )
  }
}
复制代码

效果图:

rcc2.gif

在函数式组件中使用ref:

使用useRef这一Hook可以让我们在函数式组件中使用ref,使用方法和类组件中createRef方法有点类似。

函数式组件

import React, { useState, useRef } from 'react';

export default () => {

  const [obj, setObj] = useState({account: '', age: 0});

  const inputEl = useRef();

  const handleClick = () => {
    const accountValue = inputEl.current.value;
    setObj({
      account: accountValue,
      age: 18
    });
  }

  return (
    <>
      <div>----RFC----</div>
      <div>姓名:{obj.account}</div>
      <div>
        <input ref={inputEl} type="text" />
      </div>
      <div>年龄:{obj.age}</div>
      <button onClick={handleClick}>点我</button>
    </>
  )
}
复制代码

效果图:

rfc2.gif

3 > useEffect -> 函数式组件的生命周期

在具体的项目中,我们会经常用到生命周期函数来发送请求或者是设置一些监听内容。

常用的生命周期函数有:

(1)componentDidMount

(2)componentDidUpdate

(3)componentWillUnmount;

在类组件中使用生命周期函数:

类组件中

import React, { Component } from 'react'

export default class RClassComp extends Component {

  state = {
    count: 0,
  }

  componentDidMount() {
    this.timer = setInterval(() => {
      this.setState((state) => ({count: state.count + 1}));
    }, 1000);
  };

  componentDidUpdate(preProps, preState) {
    if(preState.count >= 5) {
      this.setState({count: 0}); 
    }
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }

  render() {
    return (
      <>
        <div>当前计数为:{this.state.count}</div>
      </>
    )
  }
}
复制代码

效果图:

rcc3.gif

在函数式组件中使用生命周期函数:

函数式组件的useEffect这一hook可以看成是上面三个生命周期的整合。useEffect接收两个参数,第一个参数是个函数,第二个参数是个数组。回调函数会在组件刚挂载完毕时调用一次(相当于componentDidMount),该回调的返回值也是一个函数,这个返回的函数会在组件销毁前被调用(相当于componentWillUnmount),但是effect 的清除阶段在每次重新渲染时都会执行,而不是只在卸载组件的时候执行一次,而第二个参数代表监听的对象列表,如果不传第二个参数,则默认监听所有变量的改变,即每一次变量改变都会执行第一个参数的函数体(相当于componentDidUpdate)。传入空数组则为不监听任何变量。useEffect可以使用多次。

在函数式组件中

import React, { useState, useEffect } from 'react';

export default () => {

  const [count, setCount] = useState(0);
  let timer;

  useEffect(() => {
    if(timer) {
      return;
    }
    if(count > 5) {
      setCount(0);
    }
    timer = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => {
      clearInterval(timer);
    };
  }, [count]);

  return (
    <>
      <div>----RFC----</div>
      <div>当前计数为:{count}</div>
    </>
  )
}
复制代码

效果图:

rfc3.gif

为什么使用React Hooks?

(1) 在组件之间复用状态逻辑很难 -> 使用自定义Hook实现复用状态,而不是使用render props高阶组件等复杂且麻烦的方法。

(2) 复杂组件变得难以理解 -> 不同的生命周期函数编写过于分散,Hook将组件中相互关联的部分拆分成更小的函数。

(3) 难以理解的 class -> 需要时刻注意维护、绑定this,使得组件编写需要小心翼翼。

(4) class 也给目前的工具带来了一些问题。

通过上面的代码对比,我们可以发现,使用函数式组件,利用hooks可以让函数式组件完全拥有类组件的三大属性和生命周期函数,而且还免去了对this的操作,用过vue的小伙伴应该对这个非常熟了,vue2到vue3的升级,对于编码过程的改变最为明显的应该就是不再使用this,在用习惯了类组件后刚接触函数式组件时,感觉怎么写怎么别扭,但是用久了之后发现,真香。

写在最后 (^.^)

如果觉得我写的还不错的话,可以赏我个点赞哦^.^

如果有写错的地方、写的不好的地方也请大家指出,供我纠正。

我是CoCoyY1,一个记录自己学习的前端热爱者。

我的其他文章

Vue3中的expose函数 ———— 控制组件被ref时暴露的对象内容

vue3新语法糖——setup script ———— 使vue3的setup书写更简便,组件免注册、变量不用返回

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享