前言
上一篇在玩 流动边框 的时候,发现 useState 更新变量之后不能获取到最新的值,而采用 useRef 去存储变量。
在查略了一些资料关于 useState 和 useRef 的区别之后,依旧有些不理解,遂向比我厉害的人请教了下,于是有了这篇的记录。
正文
setCount 之后打印的 count 值依旧是 0,是由于 useState 异步执行而 状态的行为像快照。
import { useEffect, useState } from 'react';
export default function Test() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(1, count);
setCount(1);
console.log(2, count);
}, []);
}
想看最新的值,要么将 console.log(count) 放在 useEffect 之外,要么将 count 作为 useEffect 的依赖项,即
import { useEffect, useState } from 'react';
export default function Test() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(1);
}, []);
useEffect(() => {
console.log(count);
}, [count]);
}
类组件写法:this.setState 的第二个参数接收一个回调函数,可以通过它获取最新的值。
再回归 流动边框:
'use client';
import { useEffect, useMemo } from 'react';
import { useImmer } from 'use-immer';
import styles from './styles.module.css';
export default function Effect() {
const [pos, updatePos] = useImmer({ x: 0, y: 50 });
const [done, setDone] = useImmer(false);
const background = useMemo(() => {
return `radial-gradient(20% 40% at ${pos.x}% ${pos.y}%, red 0%, transparent 100%)`;
}, [pos]);
function move() {
const { x, y } = pos;
if (x >= 0 && x < 50 && y <= 50 && y > 0) {
updatePos({ x: x + 1, y: y - 1 }); // 50 0
} else if (x >= 50 && x < 100 && y >= 0 && y < 50) {
updatePos({ x: x + 1, y: y + 1 }); // 100 50
} else if (x <= 100 && x > 50 && y >= 50 && y < 100) {
updatePos({ x: x - 1, y: y + 1 }); // 50 100
} else if (x <= 50 && x > 0 && y <= 100 && y > 50) {
updatePos({ x: x - 1, y: y - 1 }); // 0 50
}
}
useEffect(() => {
if (!done) requestAnimationFrame(move);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [pos, done]);
return (
<div className={styles.button}>
<button>CLICK</button>
<span style={{ background }}></span>
</div>
);
}