跟着案例一次搞定React-Hooks

1. React Hooks 是什么

React Hooks 是 React V16.8 版本新增的特性,即在不编写类组件的情况下使用 state 以及 React 的新特性。React 官网提供了 10 个 Hooks API,来满足我们在函数组件中定义状态,提供类似生命周期的功能和一些高级特性。

2. Hooks 的诞生背景

2.1. 类组件的不足

  • 状态逻辑难以复用:
    在旧版本的 React 中,想要实现逻辑的复用,需要使用到HOC或者Render Props,增加了组件的使用层级,同时学习使用成本也比较高。
  • 使用趋于复杂且维护成本较高
    有多个监听状态的生命周期,同一个功能的整个过程可能要在不同的生命周期完成,不够统一;尤其是引入 Redux 后,会变得复杂,维护成本较高。
  • this 绑定问题
    在类组件中如果不使用箭头函数,需要显示的绑定 this,容易造成 this 丢失,导致数据混乱。

2.2. Hooks 的优势

  • 自定义 Hooks 可以实现公共的逻辑抽离,便于复用
  • 可以将组件抽成更小的函数单元,实现一个函数只关注一个功能,更加清晰
  • 更加丰富的性能优化手段
  • 组件树层级变浅,使用 HOC/Render Props 实现组件的状态复用,会增加组件的层级,但 Hooks 无需增加层级即可实现。

3. 10 个官方 Hooks 案例详解

3.1. useState

import React, {
    useState } from 'react';
import ReactDOM from 'react-dom';
import {
    Button,Modal } from 'antd'
/**
 * useState:定义组件的状态
 * 作用:
 * 通过传入 `useState` 参数后返回一个带有默认状态和改变状态函数的数组。通过传入新状态给函数来改变原本的状态值。
 */

// 类组件写法
class Example extends React.Component {
   
  constructor() {
   
    super()
    this.state = {
    count: 0}
  }
  render() {
   
    return (
      <div>
        <div>你点击了{
   this.state.count}</div>
        <button onClick={
   () => this.setState({
   count: this.state.count +1})}>点击</button>
      </div>
    )
  }
}
// hooks 写法
function Example1() {
   
  // 定义一个count变量,赋初始值0
  const [count,setCount] = useState(0)
  return (
    <div>
      <div>你点击了{
   count}</div>
      <button onClick={
   () => setCount(count +1 )}>点击</button>
    </div>
  )
}
// setCount 接收函数作为参数
function Example2() {
   
  const [count,setCount] = useState(0)
  // preCount 参数为上一次的值
  const countAction = (preCount,a) =>  preCount + a
  return (
    <div>
      <div>你点击了{
   count}</div>
      <button onClick={
   () => setCount(countAction(count,1))}>点击</button>
    </div>
  )
}
/**
 * 2 . renderProps 和 hooks 的比较。彻底理解 hooks 的价值和优点。
 */
// renderProps 抽离公共逻辑
class Toggle extends React.Component {
   
  // 定义默认属性
  state= {
    on: false}
  constructor(props) {
   
    super(props)
    // 接收父组件传递的参数
    this.state.on = this.props.initial
  }
  toggle = () => {
   
    this.setState({
    on: !this.state.on })
  }
  render() {
   
    // 向子组件传递了属性和方法
    return this.props.children(this.state.on,this.toggle)
  }
}
function Example3() {
   
  return (
    <Toggle initial={
   false}>
      {
   /* 通过一个方法接收参数 */}
      {
   
        (on,toggle) => (
          <React.Fragment>
            <Button type="primary" onClick={
   toggle}>打开弹框</Button>
            <Modal visible={
   on} onOk={
   toggle} onCancel={
   toggle}>我是弹框</Modal>
          </React.Fragment>
        )
      }
    </Toggle>
  )
}

// hooks 写法 - 优势:多个状态不会产生嵌套
function Example4 () {
   
  const [visible,setVisible] = useState(false)
  return (
    <div>
      <Button type='primary' onClick={
   () => setVisible(true)}>打开弹框</Button>
      <Modal visible={
   visible} onOk={
   () => setVisible(false)} onCancel={
   () => setVisible(false)}>我是弹框内容</Modal>
    </div>
  )
}

const App = props => <div>
  <Example />
  <hr />
  <Example1 />
  <hr/>
  <Example2/>
  <hr />
  <Example3 />
  <hr />
  <Example4 />
</div>

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

3.2. useEffect

import React, {
    useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import {
    Button,Modal } from 'antd'
/**
 * useEffect: 处理副作用(副作用:指那些没有发生在数据向视图转换过程中的逻辑,如 ajax 请求、访问原生dom 元素、本地持久化缓存、绑定/解绑事件、添加订阅、设置定时器、记录日志等。)
 * 作用:  函数组件能保存状态,但是对于异步请求,副作用的操作还是无能为力,所以 React 提供了 useEffect 来帮助开发者处理函数组件的副作用,类似生命周期函数,相当于是 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合,可以通过传参及其他逻辑,分别模拟*这三个生命周期函数。
 * useEffect具有以下5个特性:
 * 1. 第一次渲染时执行,任何状态发生变化都执行 - 只指定一个回调函数作为参数, 相当于componentDidMount & componentDidUpdate
 * 2. 第一次渲染执行,任何状态发生变化时不执行
 * 3. 第一次渲染执行,通过第二个参数指定状态发生变化时执行,其他状态发生变化不执行
 * 4. 监听多个状态时,可以同时定义多个useEffect
 * 5. 组件卸载时会执行回调函数返回的回调函数 - 相当于componentWillUnmount
 * 6. 未传递第二个参数,所有状态更新就执行useEffect,或者指定状态,对应状态更新执行useEffect时,会先执行返回值回调,再执行第一个回调参数(第二个参数为空数组时任何状态更新都不会执行)
 *

/**
 * 1. useEffect只有一个回调函数作为第一个参数时:
 *   1.1.初始化时会执行一次回调函数
 *   1.2.任一一个状态数据发生变化时都会执行回调函数
 */
function Example () {
   
  const [count,setCount] = useState(0)
  useEffect(() => {
   
    // 初始化时执行一次,count每次变化的时候都会执行
    console.log('我执行啦!')
  })
  return (
    <div>
       <div>点击了{
   count}</div>
      <Button type='primary' onClick={
   () => setCount(count+1)}>点击</Button>
    </div>
  )
}

/**
 * 2. useEffect传入两个参数:第一个参数是回调函数,第二个参数是空数组:
 *    useEffect的回调函数只会在初始化渲染时执行一次
 */
function Example1() {
   
  const [count,setCount] = useState(0)
  useEffect(() => {
   
    // 只会在初次渲染时执行,任何状态数据发生变化都不会执行
    console.log('我执行啦111111!')
  },[])
  return (
    <div>
      <div>你点击了{
   count}</div>
      <Button type='primary' onClick={
   () => setCount(count + 1)}>点击</Button>
    </div>
  )
}

/**
 * 3. useEffect 传入两个参数,第一个是回调函数,第二个是指定数据的数组
 *   3.1 初次渲染时执行一次回调函数
 *   3.2 指定数据发生变化时执行一次回调函数
 */
function Example2() {
   
  const [visible,setVisible] = useState(false)
  const [count,setCount] = useState(0)
  useEffect(() => {
   
    // 初始渲染时会执行一次,visible状态发生变化时会执行,count发生变化时则不会执行
    console.log('我最帅了')
  },[visible])
  return (
    <div>
      <div>点击了{
   count}</div>
      <Button type='primary' onClick={
   () => setCount(count +1) <
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值