React18 Hooks【useState、useEffect等】

React18 Hooks

默认情况下,React函数组件是没有状态state的、没有生命周期的。react16版本后,新增了useStateuseEffect等钩子函数,让现在的函数组件具有了之前类组件的同等效力。解决了类组件在实际开发中的一些痛点

1、useState

让函数组件拥有了状态,类似Vue中的ref、reative。开发中,为了让数据更新视图,才会赋予这个数据以状态,否则这个数据还是作为普通局部变量的好

import { useState } from 'react'

const Home = () => {
  const [count, setCount] = useState(0)
  const add = () => {
    setCount(count + 1)
  }
  return (
    <>
     	<span>{count}</span>
      	<button onClick={add}>+</button>
    </>
  )
}
export default Home

注意: setCount会更新组件

2、useEffect

让函数组件拥有生命周期,useEffecthook即是:类组件中componentDidMount、componentDidUpdate、componentWillUnmounted这三个钩子的功能组合

import { useState, useEffect } from 'react'

const Home = () => {
  const [count, setCount] = useState(0)
  const add = () => {
    setCount(count + 1)
  }
  // 接收一个参数时:组件加载完成和组件状态更新时 执行
  useEffect(function () {
    console.log('zhw')
  })
  
  // 如果只希望函数挂载完后,执行一次,组件状态变化不再执行,可以传空数组
  useEffect(function () {
    console.log('zhw')
  }, [])
  
  // 接收参数二时,参数二是一个数组,用于指定依赖数据,用于当依赖数据变化时,执行一次回调
  // 1、组件挂载完后执行一次;2、仅仅当count的状态更新,执行一次
  useEffect(function () {
    console.log('zhw')
  }, [count])

  // 组件卸载之前按
  // 1、
  useEffect(function () {
    return function () {
      // 该子函数会在组件    即将卸载  和   状态更新 的时候,自动执行
      console.log('组件卸载了')
    }
  })  
  // 2、
  useEffect(function () {
    return function () {
      // 该子函数会在组件    仅仅在 即将卸载  的时候,自动执行
      console.log('组件卸载了')
    }
  }, []) 
  return (
    <>
    	<span>{count}</span>
      	<button onClick={add}>+</button>
    </>
  )
}
export default Home

3、useRef

允许在函数组件中使用ref属性 操作元素或者组件对象,useRef底层使用的就是createRef

  1. 获取单个元素对象
import React, { useState, useRef } from 'react'

const Home = () => {
  const [count, setCount] = useState(0)
  // React.MutableRefObject: 因为numRef 可能undefined
  const numRef = useRef() as React.MutableRefObject<HTMLHtmlElement>

  const add = () => {
    setCount(count + 1)
    // useRef().current: 获取元素或者组件对象
    console.log(numRef.current)
  }
  return (
    <>
      <button onClick={add}>+</button>
      <span ref={numRef}>{count}</span>
    </>
  )
}
export default Home
  1. 获取列表元素对象

只需借用ref属性,不需要使用useRef()

const Home = () => {
  const hobbies = ['唱跳', 'rap', '篮球']
  // 这块使用普通对象
  const hobbyRefList: HTMLElement[] = []

  const getHobbyEle = () => {
    // 更新rap背景色
    hobbyRefList[1].style.background = 'skyblue'
  }
  return (
    <>
      <ul>
        {hobbies.map((item) => (
          <li
            ref={(el: HTMLLIElement) => {
              hobbyRefList.push(el)
            }}
            key={item}
          >
            {item}
          </li>
        ))}
      </ul>
      <button onClick={getHobbyEle}>获取爱好列表元素对象</button>
    </>
  )
}
export default Home
  1. 获取函数组件对象

react18中无法直接通过ref属性获取组件对象,因为react18中,函数组件没有实例。直接使用ref会报错: Function components cannot be given refs。既然无法获取实例,则需要想其他办法,获取组件状态和方法.此时可以使用React内置的高阶组件:React.forwardRef: 用于处理函数组件,可以将ref属性传递到函数组件内部

子组件中

import { useState, forwardRef, useImperativeHandle } from 'react'

// props: 父组件通过自定义属性传递的数据
// ref: 把父组件传递的ref属性和函数子组件元素建立对应关系
const Header = (props: object, ref: any) => {
  console.log(props, ref)

  const [title, setTitle] = useState('头部组件')
  // 用于子组件 向父组件 暴露方法
  // 类似于Vue3的 defineExpose
  useImperativeHandle(ref, () => ({
    updateTitle: (title: string) => {
      setTitle(title)
    }
  }))

  return (
    <>
      <div ref={ref}>{title}</div>
    </>
  )
}

export default forwardRef(Header)

关键词: forwardRefuseImperativeHandle


父组件中

import { useRef } from 'react'
import Header from '@/components/Header'

const Home = () => {
  // useRef利用泛型 可以自动推导类型为: React.MutableRefObject
  // 解决: 类型“(instance: HTMLDivElement | null) => void”上不存在属性“current”
  const funCompRef = useRef<HTMLElement>()

  const getHobbyEle = () => {
    console.log(funCompRef.current)
  }
  return (
    <>
      <Header ref={funCompRef} />
      <button onClick={getHobbyEle}>获取爱好列表元素对象</button>
    </>
  )
}
export default Home

你可能感兴趣的:(javascript,前端,react.js)