React hook常见用法

1.hook 是什么

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

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。

2.为什么要使用 hook(使用 hook的好处)

  • 提供涉及state和生命周期钩子逻辑的抽象和复用,解决了过去因为和组件耦合导致的state和钩子的复用问题
  • 将props的链式数据传导转化为横切式的传导方式,减少了props的传导层级,简化了结构
  • 使函数组件也能操作state,完善了函数式组件的功能,避免了因为逻辑的复杂化时要把函数组件改成class组件的麻烦
  • 和render-props/高阶组件实现方案的对比:比起别扭的render-props来,Hook的代码结构清晰明了。而相比起高阶组件,hook有内置的API,使用起来更简单方便

3.useState:让函数式组件拥有状态(异步更新)

class 示例:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>Click me</button>
      </div>
    );
  }
}

// 计数器
import { useState } from 'react'
const Test = () => {
    const [count, setCount] = useState(0);
    return (
        <>
            <h1>点击了{count}</h1>
            <button onClick={() => setCount(count + 1)}>+1</button>
        </>
    );
}
export default Test

在 useState()中,它接受状态的初始值作为参数,即上例中计数的初始值,它返回一个数组,其中数组第一项为一个变量,指向状态的当前值。类似 this.state,第二项是一个函数,用来更新状态,类似 setState。

上述例子中没有 class 继承、没有 this、没有生命周期、代码更加简洁、这就是使用 hooks 的意义;

PS:class组件中this.setState更新是state是合并, useState中setState是替换。例如:
// 错误示例
import { useState } from 'react'
const Test = () => {
    const [counts, setCounts] = useState({
        num1: 0,
        num2: 0
    });
    return (
        <>
            <h1>num1:{counts.num1}</h1>
            <h1>num2:{counts.num2}</h1>
            {/* //错误写法 可以看到useState中setState是替换,不会合并
	     	<button onClick={() => setCounts({ num1: counts.num1 + 1})}>num1+1</button>  
	       	<button onClick={() => setCounts({ num2: counts.num2 + 1})}>num2+1</button> */}
	            
            <button onClick={() => setCounts({ ...counts, num1: counts.num1 + 1})}>num1+1</button>
            <button onClick={() => setCounts({ ...counts, num2: counts.num2 + 1})}>num2+1</button>
        </>
    );
}
export default Test
PS:useState的异步更新
 const [list, setlist] = useState([0]);

  function change(){
     setlist([22, 1])
     console.log(list) //我想这里直接获得[22,1],但是拿到的是[0]
  }

   useEffect(() => {
        console.log(list)
    }, [list]

useState每次执行会返回一个新的state(简单类型的等值拷贝)
setState会触发UI更新(重新render,执行函数组件)
由于UI更新是异步任务,所以setState也是一个异步过程

解决方法(再写一个副作用Hook,只用于监视list值的变化,从而进行操作)

4.useEffect:副作用,取代生命周期

Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
React中的副作用操作:

    1.发ajax请求数据获取
   	2.设置订阅 / 启动定时器
    3.手动更改真实DOM
	useEffect(() => { 
	       // 在此可以执行任何带副作用操作
	        return () => { // 在组件卸载前执行
	          // 在此做一些收尾工作, 比如清除定时器/取消订阅等
	        }
	 }, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行

useEffect的基本用法:

1.默认是状态中任何数据发生变化副作用都会执行,父组件重新render 也会触发执行
2.useEffect第二个参数传入需要绑定的状态,可绑定多个;如果指定的是[], 回调函数只会在第一次render()后执行
3.清理副作用,return一个函数,作用相当于卸载钩子函数componentWillUnmount() 
4.可以把 useEffect Hook 看做如下三个函数的组合
    componentDidMount()
    componentDidUpdate()
	componentWillUnmount() 
import { useState, useEffect } from 'react'
const Test = () => {
    const [count1, setCount1] = useState(0);
    const [count2, setCount2] = useState(0);
    useEffect(() => {
        console.log('useEffect触发了---')
    });
	// 语法:useEffect(回调函数,[依赖值])
	useEffect(() => {
	    console.log('useEffect触发了')
	}, [count1]);
    return (
        <>
            <h1>count1:{count1}</h1>
            <h1>count2:{count2}</h1>
            <button onClick={() => setCount1(count1 + 1)}>count1+1</button>
            <button onClick={() => setCount2(count2 + 1)}>count2+1</button>
        </>
    );
}
export default Test

清理副作用:
在上面的操作中都不用清理的副作用,然而,有些副作用是需要去清理的,不清理会造成异常甚至内存泄漏,比如开启定时器,如果不清理,则会多次开启,从上面可以看到useEffect的第一个参数是一个回调函数,可以在回调函数中再返回一个函数,该函数可以在状态更新后第一个回调函数执行之前调用,具体实现:

useEffect(() => {
    // 设置副作用
    return () => {  // 在组件卸载前执行
        // 清理副作用   // 在此做一些收尾工作, 比如清除定时器/取消订阅等
    }
});

6.useRef:功能与React.createRef()一样

Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据

// 用法:例如要实现点击button按钮使input输入框获得焦点:
import React, { useRef } from 'react';
const Test = () => {
    const inputEl = useRef();
    return (
        <>
            <input ref={inputEl} />
            <button onClick={() => inputEl.current.focus()}>focus</button>
        </>
    );
}
export default Test

7.useContext:跨组件共享数据

8.useCallback:性能优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值