React Hook概述

Unsplash

Hook 是什么?Hook 是 React 16.8 的新增特性,它可以让你在不编写 class 的情况下“钩入” React 的特性,例如,useState 是允许你在 React 函数组件中添加 state 的 Hook

1. State Hook

useState 是一种新方法,它与 class 里面的 this.state 提供的功能完全相同。一般来说,在函数退出后变量就会“消失”,而 state 中的变量会被 React 保留,useState() 方法里面唯一的参数就是初始 state,我们可以使用 numberstring 对其进行赋值,其返回值为当前的 state 以及更新 state 的函数

// src/comments/LikeButton.js
import React, { useState } from 'react'

// 函数型组件
const LikeButton = () => {
  const [ like, setLike ] = useState(0)
  console.log(useState(0))
  return (
  <button onClick={() => {setLike(like + 1)}}>
    喜欢数 {like}
  </button>
  )
}

export default LikeButton

随后在 App.js 中引入该组件,效果如下图所示

LikeButton组件

上面的 Hook 代码通过 class 组件进行编写,如下所示

class LikeButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      like: 0
    };
  }

  render() {
    return (
      <button onClick={() => this.setState({ like: this.state.like + 1 })}>
        喜欢数 {this.state.like}
      </button>
    );
  }
}

2. Effect Hook

在 React 更新 DOM 之后我们如果想要运行一些额外的代码,比如发送网络请求,手动变更 DOM,记录日志,订阅外部数据源等等,我们就会使用到 Effect Hook,类似于 Vue 中的 nextTick 方法

而在 React 的 class 组件中,我们会把同样的操作放到 componentDidMountcomponentDidUpdate 函数中,需要在两个生命周期函数中编写重复的代码

componentDidMount() {
  document.title = `You clicked ${this.state.like} times`;
}
componentDidUpdate() {
  document.title = `You clicked ${this.state.like} times`;
}

使用 useEffect 执行相同的操作,代码如下所示

const LikeButton = () => {
  const [ like, setLike ] = useState(0)
  
  useEffect(() => {
    document.title = `You clicked ${like} times`;
  })
  
  return (
  <button onClick={() => {setLike(like + 1)}}>
    喜欢数 {like}
  </button>
  )
}

useEffect 组件

useEffect 在默认情况下,在第一次渲染之后以及每次更新之后都会执行,只需要知道 effect 发生在渲染之后,而不用再去考虑是挂载还是更新状态,Effect 组件在需要清除的时候,可以通过返回一个函数进行清除,React 将会在执行清除操作时调用它

// comments/MouseTracker.js
import React, { useState, useEffect } from 'react'

function MouseTracker() {
  const [ positions, setPositions ] = useState({x: 0, y: 0})
  useEffect(() => {
    const updateMouse = e => {
      setPositions({x: e.clientX, y: e.clientY})
    }
    document.addEventListener('click', updateMouse)
    return () => {
      document.removeEventListener('click', updateMouse)
    }
  })
  return (
    <p>X: {positions.x}, Y: {positions.y}</p>
  )
}

export default MouseTracker

如果某些特定值在两次重渲染之间没有发生变化,可以传递数组作为 useEffect 的第二个可选参数,就能够通知 React 跳过对 effect 的调用

useEffect(() => {
  document.title = `You clicked ${like} times`;
}, [count]); // 仅在 like 更改时更新

关于 Hook 的更多使用方法,可在 useHooks 中查看相关例子

3. 自定义 Hook

自定义 Hook,就是将组件逻辑提取到可重用的函数中

// hooks/useURLLoader.js
import { useState, useEffect } from 'react'
import axios from 'axios'

const useURLLoader = (url) => {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(false)
  useEffect(() => {
    setLoading(true)
    axios.get(url).then(result => {
      setData(result.data)
      setLoading(false)
    })
  }, [url])
  return [data, loading]
}

export default useURLLoader
// App.js
const CatShowWithHook = () => {
  const [ category, setCategory ] = useState('1')
  const [ data, loading ] = useURLLoader(`https://api.thecatapi.com/v1/images/search?limit=1&category_ids=${category}`)
  return (
    <>
      <button onClick={() => { setCategory('1') }}>帽子猫</button>
      <button onClick={() => { setCategory('5') }}>盒子猫</button>
      {loading ? <p>新猫咪读取中</p>
       : <img src={data && data[0].url} alt="cat" style={{width: 300}} />
      }
    </>
  )
}

自定义 Hook

参考资料 React 官网 - 使用 State Hook React 官网 - 使用 Effect Hook React 官网 - 自定义 Hook

本篇的内容到这里就全部结束了,源码我已经发到了 GitHub React_02 上了,有需要的同学可自行下载

End of File

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • React 基础知识

    在正式讲解 React 之前,我们需要对 WebPack 部分做一个简单的介绍,而 WebPack 0 基础的同学,可以先参考 WebPack 模块化打包工具(...

    Nian糕
  • 聊聊原型 Prototype | 技术创作101训练营

    原型和原型链,一直是 JavaScript 中的重要概念,也是面试官必问的知识点,或许有的同学认为,自己虽然没有很深入了解过原型和原型链,但并不影响自己日常的开...

    Nian糕
  • ECMAScript7 async/await 异步解决方案

    Async 函数作为异步解决方案的最优解,async/await 特性能让我们编写出相比回调地狱和 Promise 链式调用更直观、更容易理解的代码,Async...

    Nian糕
  • C#中的特性(Attribute)

    个人感觉C#中的特性(Attribute)和Java中的注解(Annotation)的使用有些相似,但是有有些区别。

    卡尔曼和玻尔兹曼谁曼
  • 容易混淆的const

    (1)可以定义const常量,具有不可变性。   例如:const int Max=100; Max++会产生错误; (2)便于进行类型检查,使编译器对处理...

    海盗船长
  • 五. css 布局之 position(定位)

    包含块( containing block ) 正常情况下: 包含块就是离当前元素最近的祖先块元素,

    小海怪的互联网
  • TDD基础导读

    测试驱动开发是一种软件开发实践,源于1999年Kent Beck《Extreme Programming Explained》一书中的测试先行这一概念。Kent...

    袁慎建@ThoughtWorks
  • 技术分析 Lendf.me 被攻击,ERC777到底该不该用?

    我在去年 9 月写过一篇ERC科普文章:ERC777 功能型代币(通证)最佳实践[1] ,文章里我推荐新开发的代币使用 ERC777 标准。

    Tiny熊
  • 网页布局基础

    小胖
  • 软件敏捷开发 TDD 方案

    现在开发软件都讲敏捷开发,何为敏捷开发?敏捷开发是一种应对快速变化的需求的一种软件开发能力。它们的具体名称、理念、过程、术语都不尽相同,相对于"非敏捷",更强调...

    拾贰

扫码关注云+社区

领取腾讯云代金券