React Hooks详解

94 阅读4分钟

React包含类式组件和函数式组件。但是传统的函数式组件只能接收props,渲染UI等一些事情,能处理的逻辑远远少于类式组件,但是怎么做到既可以使用函数式组件来提高性能,又可以使用像类式组件那样的功能呢?这里就用到了Hooks。下面我会一一将React的所有Hooks都做一个讲解,此文章是针对于刚接触react Hooks的程序员,并没有涉及底层原理。

1,useState

我们知道,类组件中有三大核心属性:state,props,ref。而useState就是实现类组件中的state。

用法如下:

import {useState} from 'react'

export default function App() {
  const [state, changeState] = useState(0)
  return (
    <div>
      <span>{state}</span>
      <button onClick={() => changeState(1)}>点击改变state数据</button>
    </div>
  )
}

state就是定义的数据,changeState是一个函数,用来改变state数据并驱动视图的变化。

2,useReducer

useReducer可以理解是类似redux的API,它可以实现子组件向父组件传值,改变父组件的状态。

用法如下:

import {useReducer} from 'react'

export default function App() {
  const [state, dispatch] = useReducer((state, action) => {
    const {type} = action
    switch (type) {
      case 'add':
        return state+1
      case 'sub':
        return state-1
      default:
        return state
    }
  }, 0) // useReducer还有第三个参数(函数参数),相当于第二个参数的转换器,可以修改初始值
  return (
    <div>
      <h1>{state}</h1>
      <Son state={state} dispatch={dispatch}/>
    </div>
  )
}

const Son = function (props) {
  const demo = () => {
    props.dispatch({type: 'add'})
  }
  return (
    <div>
      <button onClick={demo}>+</button>
    </div>
  )
 }

3,useEffect

类式组件是有生命周期的,目的是为了让我们在组件从创建到销毁的中的各个节点可以做一些事情,从而增强组件的一些逻辑处理,比如我们可以在组件创建完毕之后调用后台接口获取数据,可以在数据更新的时候做一些事情,也可以在组件销毁之前做一些事情等等。而函数式组件是没有生命周期这个概念的,因此推出了useEffect来模拟一些生命周期。

用法如下:

import React, {useEffect, useState} from "react";

export default function App() {
  const [x, setX] = useState(0)
  useEffect(() => {
    console.log('组件创建完毕的回调')
  }, [])

  useEffect(() => {
    console.log('x变化的回调')
  }, [x])
  
  useEffect(() => {
    return () => {
      console.log('组件销毁的回掉')
    }
  }, [])
  return (
    <div>useEffect学习</div>
  )
}

4,useContext

此hooks是用来跨级传递数据的,传统的props方式来传值需要一级一级的传递,但是层级过深就很不方便了,而useContext就完美的解决了这个问题。

用法如下:

import React, {createContext, useContext} from "react";

const Context = createContext(undefined)
export default function App() {
 return (
   <Context.Provider value={{name: 'cuiwu', age: 18}}>
     <Son1/>
   </Context.Provider>
 )
}

function Son1() {
 const value = useContext(Context)
 console.log(value) // {name: 'cuiwu', age: 18}
 return (
   <div>
     <Son2/>
   </div>
 )
}

function Son2() {
 const value = useContext(Context)
 console.log(value) // {name: 'cuiwu', age: 18}, 实现跨级传递数据
 return (
   <div>
   </div>
 )
}

5,useRef

useRef两个作用:一个是用来获取dom元素,第二个是用来缓存数据,通过useRef缓存的数据,直到组件销毁才能清除。

用法如下:

// 获取dom对象
import React, {useRef} from "react";

export default function App() {
  const myRef = useRef() // myRef就是input对象,可以获取输入内容等信息
  const getInputValue = () => {
    console.log(myRef.current.value)
  }
  return (
    <div>
      <input type="text" ref={myRef} defaultValue='useRef第一个作用'/>
      <button onClick={getInputValue}>获取input框输入值</button>
    </div>
  )
}
缓存数据
import React, {useRef, useState} from "react";

export default function App() {
  // 实现一个加奇数次显示,偶数次不显示的功能
  const [x, setX] = useState(0)
  const value = useRef(0)
  const addValue = () => {
    value.current += 1
    setX(value.current)
  }
  const isJi = () => value.current % 2 !== 0
  return (
    <div>
      {isJi() ? <h1>{x}</h1> : ''}
      <button onClick={addValue}>点击+1</button>
    </div>
  )
}

6,useMemo

useMemo 可以在函数组件 render 上下文中同步执行一个函数逻辑,这个函数的返回值可以作为一个新的状态缓存起来。那么这个 hooks 的作用就显而易见了:

场景一:在一些场景下,需要在函数组件中进行大量的逻辑计算,那么我们不期望每一次函数组件渲染都执行这些复杂的计算逻辑,所以就需要在 useMemo 的回调函数中执行这些逻辑,然后把得到的产物(计算结果)缓存起来就可以了。

场景二:React 在整个更新流程中,diff 起到了决定性的作用,比如 Context 中的 provider 通过 diff value 来判断是否更新


作者:我不是外星人
链接:juejin.cn/post/711893… 来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

用法如下:

import React, {useMemo, useState} from "react";
export default function App() {
  const [x, setX] = useState(1)
  const y = useMemo(() => 2*x+1, [x]) // 用来缓存一个因变量,相当于vue中的计算属性
  const changeX = () => setX(x+1)
  return (
    <div onClick={changeX}>
      <h1>x是{x}</h1>
      <h1>y是{y}</h1>
    </div>
  )
}

7,useCallback

用法与useMemo基本类似,只不过useMemo缓存的是一个函数,接着上面的代码进行扩展,如下:

import React, {useCallback, useMemo, useState} from "react";
export default function App() {
  const [x, setX] = useState(1)
  const y = useMemo(() => 2*x+1, [x]) // 用来缓存一个因变量,相当于vue中的计算属性
  const changeX = useCallback(() => setX(x+1), [x]) // 缓存的是一个函数类型
  // 使用了useMemo和useCallback,只要x值不变,就不需要重新创建一个y和changex,而是从缓存中拿,提高性能
  return (
    <div onClick={changeX}>
      <h1>x是{x}</h1>
      <h1>y是{y}</h1>
    </div>
  )
}