react 函数式组件的hooks

目录

useState

useEffect

useCallback

useMemo

useRef

useContext

useReducer

自定义hooks


useState

函数式组件的状态 ,格式: const [value,setValue] = useState( {xxxx} )

console.log([value, setValue])打印一下可以看到:

  • value-----状态变量名称
  • setValue-----与变量相对应的一个更改状态值的方法
  • {xxxx} -----状态的初始值,对象、数组、函数、字符串等都可以

简单使用示例:

import './App.css';

import React, {useState} from 'react'


export default function App() {

  const [value, setValue] = useState({id:0,name:'蔡某坤'})

  console.log([value, setValue])
  return (
    <div>
        <button onClick={()=>setValue({id:1,name:'英雄可以受委屈,但你不能踩我的切尔西'})}>改变</button>
        <div>{value.name}</div>
    </div>
  )
}


useEffect / useLayoutEffect

  useEffect(() => {
    console.log("我被执行了")
    //setValue({id:1,name:'英雄可以受委屈,但你不能踩我的切尔西'})
    return ()=>{}
  },[value]);
  •  useEffect

        useEffect相当于componentDidMount、componentDidUpdate、componentWillUnmount的合并。在一开始的时候会默认执行两遍,后续每次重新渲染时会调用一次:

         此方法有第二个参数,第二个参数为useState变量的依赖。不加第二个参数就是普通的componentDidMount + componentDidUpdate; 加了第二个参数则表示对指定状态进行监听,只有被指定的状态发生改变时才会执行,类似于Vue的watch、computed,需要注意的是,如果加了第二个参数就不能在此方法内对指定状态的修改,否则会造成死循环。

        回调函数用于清空一些事件监听:

import './App.css';
import React, {useState,useEffect} from 'react'

export default function App() {

  const [value, setValue] = useState(true)

  return (
    <div>
        <button onClick={()=>setValue(!value)}>改变</button>
        {value? <A/>:'子组件已被销毁'}
    </div>
  )
}

function A() {
  
  const [value, setValue] = useState(0)

  useEffect(() => {
    var times=setInterval(() => {
      console.log("英雄可以受委屈,但你不能踩我的切尔西")
      setValue(value+1)
    }, 1000);
    return ()=>{clearInterval(times)}
  });

  return (
    <div>
        <div>我是子组件{value}</div>
    </div>
  )
}
  • useLayoutEffect

useLayoutEffect 和 useEffect的区别在于调用的时机不同,useLayoutEffect是在DOM更新完成后,页面渲染之前调用的,useEffect则是在页面完成渲染后执行的。同样的,componentDidMount 和componentDidUpdate也是在DOM更新完成后,页面渲染之前调用的,使用useLayoutEffect可能会造成页面的阻塞,而useEffect则可能会造成页面抖动。


useCallback

         useCallback(记忆函数)。当setCount触发时,会将整个函数内所有东西都进行重新执行,内部的方法自然而然地也会被重新定义,此时使用useCallback可以有效地减少函数的创建,重新渲染时并不会去执行它。

        useCallback有两个参数,第一个参数为方法,第二个参数为[ xxx ],其中xxx为定义的状态名称。当第二个参数不填或者为空数组时,其内部的值是不变的,永远都是上一次初始化缓存下来的值;当填入相关的副作用,如下面例子的 [ ] 替换成 [ count ] 时,当count这个值发生改变时,useState会自动缓存下此次更新的值,有些许类似Vue中的计算属性。

import React, { useCallback, useState } from 'react'

export default function App() {

  const [count, setCount] = useState(0);

  const add =useCallback( () => {
    setCount(count + 1)
  },[])

  return (
    <div>
      <button onClick={() => { add() }}>增加</button>
      {count}
    </div>
  )
}

useMemo

        useMemo与useCallback 相类似:useCallback返回你传入的函数,useMemo返回一个值;useCallback传入的方法不会自动执行,useMemo传入的方法会自动执行。

import React, { useMemo, useState } from 'react'

export default function App() {

  const [count, setCount] = useState(0);

  const add =useMemo( () => {
    console.log("我被执行了")

    return count
  },[count])   

  return (
    <div>
      <button onClick={() => { setCount(add + 1) }}>增加</button>
      {count}
      <hr></hr>
      <div>add方法自动返回:{add}</div>
    </div>
  )
}


useRef

跟类组件的ref一样,通过绑定获取DOM节点。

import React, { useMemo, useRef, useState } from 'react'

export default function App() {

  const [text, setText] = useState("");

  const input_ref=useRef();

  return (
    <div>
      <input ref={input_ref} onChange={()=>setText(input_ref.current.value)}></input>
      <div>输入框的值:{text}</div>
    </div>
  )
}

 


useContext

函数式组件的提供者与消费者,示例如下:

import React, { useContext, useRef, useState } from 'react'

const context = React.createContext()

export default function App() {

  const [text,setText]=useState("")
  const input_ref=useRef()

  return (
    <div>
      <context.Provider value={text}>
        <div>我是父组件:{text}</div>
        <input ref={input_ref} onChange={() => setText(input_ref.current.value)}></input>
        <A/>
      </context.Provider>
    </div>
  )
}

function A() {

  const A_context = useContext(context)

  return (
    <div>
      <hr></hr>
      <div>我是子组件,用context接收到的值:{A_context}</div>
      <hr></hr>
    </div>
  )
}

useReducer

        useReducer 全局状态管理。useState的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法,类似于类组件的订阅发布,

import React ,{useReducer}from 'react'

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    case 'reset':
      return {count: action.payload};
    default:
      throw new Error();
  }
}

 export default function App() {
  const [state, dispatch] = useReducer(reducer, {count:0});
  return (
    <>
      Count: {state.count}
      <button
        onClick={() => dispatch({type: 'reset', payload: 0})}>
        Reset
      </button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

自定义hooks

在函数式组件内使用自定义的指令,需要以use开头。

如下,我将其分割出去了两个方法: 

import React, {  useRef, useState } from 'react'

export default function App() {

  const [text,setText]=useState("")
  const input_ref=useRef()

  const input_change=()=>{
      setText(input_ref.current.value)
  }

  const input_text=()=>{
    return "【"+text+"】"
  }

  return (
    <div>
        <div>input的值:{input_text()}</div>
        <input ref={input_ref} onChange={input_change}></input>
    </div>
  )
}

 将这两个方法移动外部,函数名以“use”开头命名,然后在组件内就可以进行使用了,自定义hooks可以将组件内的方法移到外部,增加代码的直观性。

import React, { useRef, useState } from 'react'

export default function App() {

  const [text, setText] = useState("")
  const input_ref = useRef()

  const input_change = useInputChange(setText, input_ref)

  const input_text = useInputText(text)

  return (
    <div>
      <div>input的值:{input_text}</div>
      <input ref={input_ref} onChange={input_change}></input>
    </div>
  )
}

function useInputChange(setText, input_ref){
    return ()=>setText(input_ref.current.value)
}


function useInputText(text) {
  return "【"+text+"】"
}


猜你喜欢

转载自blog.csdn.net/qq_46149597/article/details/129254185