react 的钩子函数

78 阅读3分钟

useState 状态钩子

纯函数组件没有状态,该钩子为函数组件引入state,并进行数据操作

import { useState } from "react";
export default function FunctionComponent(props) {
  const [data, setData] = useState(0);

  const addOption = () => {
    setData(data + 1);
  };

  return (
    <>
      <div>{data}</div>
      <button onClick={addOption}>add </button>
    </>
  );
}

useEffect 副作用钩子 (异步执行)

用于在函数组件中进行 接口请求,订阅,监听等操作。模拟类组件中的生命周期(componentDidMount,componentDidUpdate,componentWillUnmount三个函数的组合)

// 接受两个参数,1: 异步操作函数  2:参数是一个数组

import React, { useState, useEffect } from "react";
export function FunctionComponent(props) {
  const [data, setData] = useState(0);

  // 第二个参数为空 每次渲染都会执行
  useEffect(() => {
    setData({
      data: data + 0,
    });
    return () => {
      // 卸载之后执行
    };
  });
  // 第二个参数为空数组  组件挂载后,运行一下
  useEffect(() => {
    // 相当于 componentDidMount,componentDidUpdate,componentWillUnmount
    return () => {
      // 卸载之后执行
    };
  }, []);
  // 第二个参数 有参数 ,监听参数的改变
  useEffect(() => {
    return () => {
      // 卸载之后执行
    };
  }, [data]);
  return <div>{data}</div>;
}

useContext 共享状态钩子

跨越组件层级直接传递变量,实现数据共享

import { useState, useContext, createContext } from "react";
const CountContext = createContext(0);
export default function FunctionComponent(props) {
  const [count, setCount] = useState(0);

  function addCount() {
    setCount(count + 1);
  }

  return (
    <>
      <div>{count}</div>
      <button onClick={addCount}>点击一下</button>
      {/* 通过value传值  外面要包裹 xxxContext.Provider*/}{" "}
      <CountContext.Provider value={count}>
        <Child />
      </CountContext.Provider>
    </>
  );
}
const Child = () => {
  // 获取数据
  const count = useContext(CountContext);
  return <div>子组件{count}</div>;
};

useReducer

存储和更新数据 组件传参

import  { useEffect, useReducer } from "react";

function setName(state = [], action) {
  switch (action.type) {
    case "INIT":
      return [...action.payload];
    case "REPALCE":
      return [...action.payload];
    default:
      return state;
  }
}
export default function FunctionComponent(props) {
  const [nameList, dispath] = useReducer(setName, []);
  useEffect(() => {
    dispath({ type: "INIT", payload: ["小红", "小王"] });
  }, []);
  return (
    <div>
      <NameList
        nameList={nameList}
        setName={(parms) => dispath({ type: "REPALCE", payload: parms })}
      ></NameList>
    </div>
  );
}

function NameList({ nameList, setName }) {
  const deleteItem = (index) => {
    const tem = [...nameList];
    tem.splice(index, 1);
    setName(tem);
  };

  return (
    <div>
      {nameList.map((item, index) => {
        return (
          <div key={item} onClick={(index) => deleteItem(index)}>
            {item}
          </div>
        );
      })}
    </div>
  );
}

useMemo 缓存

在react父组件改变,自组件会保持更新。比较不合理



import{ useState , useMemo} from "react"


function fn (count){
  console.log("重新渲染了")
    return count+"new"
}

function App(){
    const [count,setCount]=useState(0)
    const [num,setNum]=useState(0)

     //无论是count或者num改变,fn函数都会渲染
    // const result=fn(count)
    
    // 只有count改变的时候,才会渲染
    const result=useMemo(()=>fn(count),[count])
    return (
        {result}
        <button onClick={()=>setCount(count++)}>+</button>
        <button onClick={()=>setnum(num++)}>+</button>
    )

}


export default App

React.memo

组件在props没有改变时候,不再渲染

memo的缓存只能缓存简单类型,不能缓存引用类型,要想缓存引用类型,需要使用useMemo进行缓存



import{ useState , memo} from "react"


function Son (){
  console.log("Son重新渲染了")
    return "SON"

}
const SonMemo=memo(function Son ({count}){
    console.log("SonMemo重新渲染了")
    return count+"new"

    }
)

function App(){
    const [count,setCount]=useState(0)
    const [num,setNum]=useState(0)


    const list=[1,2,3]
    
    return (
        //无论是count或者num改变,Son都会渲染
        <Son />
         // 只有count改变的时候,才会渲染
        <SonMemo count={count} list={list}/>
        <button onClick={()=>setCount(count++)}>+</button>
        <button onClick={()=>setnum(num++)}>+</button>
    )

}


export default App

useCallback 渲染性能优化 (缓存函数本身)


import{ useState , memo ,useCallBack} from "react"



const SonMemo=memo(function Son ({handleChange}){
    console.log("SonMemo重新渲染了")
    handleChange(6666)
   
    return count+"new"

  }
)

function App(){
    const [count,setCount]=useState(0)
  
    // // 每次父组件改变,自组件都会更新渲染
    // function handleChange(num){
    //   console.log(num)
    // } 

    // 参数1:回调函数 ,参数2 :依赖数组,依赖数组变化,函数变化。依赖数字为空,表示函数永不变化

   const handleChange =useCallBack((num)=>{
      console.log(num )
     },[])

    return (
    
        <SonMemo count={count} handleChange={handleChange} />
        <button onClick={()=>setCount(count++)}>+</button>
        <button onClick={()=>setnum(num++)}>+</button>
    )

    }


export default App

React.forwardRef

import {forwardRef} from "react"
import { useRef } from "react";

const Son=()=>{
    return <div>Son</div>
}

const SonFor=forwardRef((props,ref)=>{
    return <div ref={ref}>SonFor</div>
})


function App() {
const sonRef=useRef(null)
const sonForRef=useRef(null)
    
function handleGetRef(){
     // 打印为空
    console.log(sonRef.current)
    // 可以正常打印
    console.log(sonForRef.current)
   
}
  return (
    <Son  ref={sonRef}/>
    <SonFor  ref={sonForRef}/>
    <button onClick={handleGetRef}>获取ref</button>
  )
}

export default App;

useImperativeHandle

暴露自组件的方法给父组件

import { forwardRef, useImperativeHandle } from "react"
import { useRef } from "react";



const SonFor = forwardRef((props, ref) => {
    const divRef = useRef(null)
    function getRef() {
        console.log(divRef.current)
    }

    useImperativeHandle(ref,()=>{
        return {
            getRef
        }
    })

    return <div ref={divRef}>SonFor</div>
})


function App() {

    const sonForRef = useRef(null)

    function handleGetRef() {

        // 可以正常打印
        console.log(sonForRef.current)

    }
    return (
   
    <SonFor  ref={sonForRef}/>
    <button onClick={handleGetRef}>获取ref</button>
    )
}

export default App;

自定义Hook

import React, { useState, useEffect } from "react";
export default function ClassConponent(props) {

  return <div>{useClick().toLocaleTimeString()}</div>;
  
}

// 自定义hook ,要use开头,

function useClick() {
  const [date, setData] = useState(new Date());
  useEffect(() => {
    const timer = setInterval(() => {
      setData(new Date());
    }, 10000);
    return () => clearInterval(timer);
  }, []);

  return date;
}