React自定義 usePrevious實(shí)現(xiàn)

usePrevious 代碼

const usePrevious = (preValue) => {
    const ref = useRef();
    useEffect(() => {
        ref.current = preValue;
    }, [preValue])
    
    return ref.current;
}

在代碼中使用

import React, { useState } from "react";
import usePrevious from "./usePrevious";

export default function Counter() {
  const [count, setCount] = useState(0);
  const beforevalue = usePrevious(count);
  console.log("count修改", count);
  return (
    <h1>
      Now: {count}, before: {beforevalue}
      <button onClick={() => setCount(count + 1)}>點(diǎn)擊增加</button>
    </h1>
  );
}

一些問題

  1. useRef為什么可以用來封裝成usePrevious?
  2. React-hooks的特點(diǎn) -> 每次渲染都是最新的props,所以我們無法拿到previousProps,這時候我在網(wǎng)上查閱到了usePrevious,代碼如下:
const usePrevious = (preValue) => {
    const ref = useRef();
    useEffect(() => {
        ref.current = preValue;
    }, [preValue])
    
    return ref.current;
}
  1. useRef的特點(diǎn)是如果你給他傳入了一個值,那么他在不斷的生命周期中是永遠(yuǎn)不變的?那么他為什么又會每次都精準(zhǔn)的拿到上一次的props呢?還是說這與新的生命周期有關(guān)呢?

分析代碼

我們打印一下log,看它們執(zhí)行的順序

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

export default function usePrevious(value) {
  const previous = useRef(value);
  useEffect(() => {
    console.log("usePrevious中useEffect執(zhí)行", value);
    previous.current = value;
  }, [value]);
  console.log("返回previous.current", previous.current);
  return previous.current;
}
import React, { useState } from "react";
import usePrevious from "./usePrevious";

export default function Counter() {
  const [count, setCount] = useState(0);
  const beforevalue = usePrevious(count);
  console.log("count修改", count);
  return (
    <h1>
      Now: {count}, before: {beforevalue}
      <button onClick={() => setCount(count + 1)}>點(diǎn)擊增加</button>
    </h1>
  );
}

打印結(jié)果

返回previous.current 1
count修改 2
usePrevious中useEffect執(zhí)行 2


返回previous.current 2
count修改 3
usePrevious中useEffect執(zhí)行 3

從打印結(jié)果我們看到,是先執(zhí)行同步操作,return 返回值,再執(zhí)行 count 的渲染,最后再執(zhí)行 usePrevious中 useEffect(useEffect是在每次渲染之后才會觸發(fā)的),由于useRef 會保持引用不變,所以 ref.current 的值的修改并不會引起組件重新渲染,所以即使 ref.current 的值修改了,counter組件中也不會重新執(zhí)行 usePrevious了,所以可以通過這種方式實(shí)現(xiàn),獲取原來 state的值。

useEffect很重要的一點(diǎn)是:它是在每次渲染之后才會觸發(fā)的,是延遲執(zhí)行的。而return語句是同步的,所以return的時候,ref.current還是舊值。
所以在每次的渲染過程中,usePrevious的useEffect還沒有被調(diào)用,返回的還是上一個生命周期中被賦的值

總結(jié)

  • useRef會保持引用不變,ref.current的值改變并不會引起組件重新渲染
  • React Hook中函數(shù)式組件的生命周期中,useEffect是在jsx渲染之后執(zhí)行的

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容