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)}>點擊增加</button>
</h1>
);
}
一些問題
- useRef為什么可以用來封裝成usePrevious?
- React-hooks的特點 -> 每次渲染都是最新的props袋狞,所以我們無法拿到previousProps虱黄,這時候我在網(wǎng)上查閱到了usePrevious,代碼如下:
const usePrevious = (preValue) => {
const ref = useRef();
useEffect(() => {
ref.current = preValue;
}, [preValue])
return ref.current;
}
- useRef的特點是如果你給他傳入了一個值柳弄,那么他在不斷的生命周期中是永遠不變的?那么他為什么又會每次都精準(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)}>點擊增加</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了裤翩,所以可以通過這種方式實現(xiàn),獲取原來 state的值调榄。
useEffect很重要的一點是:它是在每次渲染之后才會觸發(fā)的踊赠,是延遲執(zhí)行的。而return語句是同步的每庆,所以return的時候筐带,ref.current還是舊值。
所以在每次的渲染過程中缤灵,usePrevious的useEffect還沒有被調(diào)用伦籍,返回的還是上一個生命周期中被賦的值
總結(jié)
- useRef會保持引用不變蓝晒,ref.current的值改變并不會引起組件重新渲染
- React Hook中函數(shù)式組件的生命周期中,useEffect是在jsx渲染之后執(zhí)行的