react Hooks浅谈

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

useState

import React,{useState} from 'react'
function HelloWorld(){
 const [count, setCount]=useState(0);
 return (
   <div>
     <p>{count}次</p>
     <button onClick={()=>setCount(count+1)}>点击</button>
   </div>
 )
}

useState 它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并;useState中0属于初始值,初始 state 参数只有在第一次渲染时会被用到;

useEffect

import React,{useState,useEffect} from 'react'
function HelloWorld(){
 const [count, setCount]=useState(0);
 // 相当于componentDidMount 和 componentDidUpdate
 useEffect(()=>{
   // 使用浏览器的Api更新页面标题
   document.title=`${count}次`
 })

 return (
   <div>
     <p>{count}次</p>
     <button onClick={()=>setCount(count+1)}>点击</button>
   </div>
 )
}

useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API

Hook 就是 JavaScript 函数,但是使用它们会有两个额外的规则:
1、只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
2、只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。

并非所有 effect 都可以被延迟执行。例如,一个对用户可见的 DOM 变更就必须在浏览器执行下一次绘制前被同步执行,这样用户才不会感觉到视觉上的不一致。(概念上类似于被动监听事件和主动监听事件的区别。)React 为此提供了一个额外的 useLayoutEffect Hook 来处理这类 effect。它和 useEffect 的结构相同,区别只是调用时机不同。

useContext

const value = useContext(MyContext);

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。
当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值。即使祖先使用 React.memo 或 shouldComponentUpdate,也会在组件本身使用 useContext 时重新渲染。

useReducer

import { useReducer } from 'react'
const updateReducer = (num: number) => (num + 1) % 1_000_000
/**
 * 让组件触发一次刷新操作
 */
const useUpdate = () => {
  const [, update] = useReducer(updateReducer, 0)
  return update
}
export default useUpdate
两种方式
1, 将初始 state 作为第二个参数传入 useReducer 是最简单的方法
2, 惰性地创建初始 state。为此,需要将 init 函数作为 useReducer 的第三个参数传入,这样初始 state 将被设置为 init(initialArg)。

useCallback

useMemo

import React,{useMemo,useState,useEffect} from 'react'
useMemo(
    () =>
      schema.enum?.map((item: any) => ({
        name: item.value,
      })),
    [schema]
  )
注:传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo。
如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值

useRef

import React,{useRef} from 'react'
function HelloWorld(props){
 const valueRef = useRef({})
 const value = { ...valueRef.current }
}

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变

useImperativeHandle

useLayoutEffect

  import {useLayoutEffect} from 'react'
  useLayoutEffect(() => {
      cropperRef.current = new Cropper(imgRef.current, {
        ...cropperProps
      })
    return () => {
      cropperRef.current?.destroy()
    }
  }, [cropperProps])

其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。
尽可能使用标准的 useEffect 以避免阻塞视觉更新。

useDebugValue

posted @ 2021-04-13 16:43  初春的暖风  阅读(77)  评论(0)    收藏  举报