React数据存储与更新
在项目中,通过一个变量的状态来判断执行什么函数,或者是通过一个变量的值来控制页面的渲染是很常见的事情,下面记录一下我对值更新的理解,先放结论。
- 普通var, let, const定义的变量
值的更改:同步,改后即得
修改过程中是否重刷页面:否
是否跨生命周期:否 - useState定义的变量
值的更改:异步,改后拿不到
修改过程中是否重刷页面:是
是否跨生命周期:是 - useRef存储的变量
值的更改:同步,改后即得
修改过程中是否重刷页面:否
是否跨生命周期:是
普通定义的变量
普通定义的变量是指我们使用var、let来定义的变量,当我们用这种类型的值来进行操作时,会有相当大的弊端。最好将这种类型的值当做一个常量const去使用,而不要通过他的改变来操作事件或控制页面更新,原因看下面的例子。
const Test = () => {
const [count, setCount] = useState(0);
var value = false;
console.log("------valueOut-------", value);
useEffect(() => {
console.log("----valueEffect-----", value);
if (value) {
console.log("------我执行了value------");
} else {
value = true;
if(value) {
console.log("------valueIn-------", value);
}
}
}, [count]);
return (
<>
<div>`The value is ${count}, The double value is `;</div>
<button
onClick={() => {
console.log("--------我点击了按钮-----");
setCount(count + 1);
}}
>
按钮
</button>
</>
);
};
/**
* 输出如下:
* ------valueOut------- false
----valueEffect----- false
------valueIn------- true
--------我点击了按钮-----
------valueOut------- false
----valueEffect----- false
------valueIn------- true
*/
可以看到初始值和进入Effect后值都为false,而且在手动更新值后立马打印出了valueIn,表明值是同步立刻被更新的,但是在更新后并没有重新打印out,说明更新值时不会重刷页面。
他的弊端就在于,当通过点击按钮刷新页面触发更新的钩子时,他的值又被重新定义了false,且我执行了value也没有被打印。因此,用它来做逻辑是不可能的。
useState定义的变量
const [state, setstate] = useState(false);
console.log("------stateOut-------", state);
useEffect(() => {
console.log("----stateEffect-----", state);
if(state) {
console.log("------我执行了state------");
} else {
setstate(true);
console.log("-----stateChange--------", state);
if(state) {
console.log("------stateIn-------", state);
}
}
/** 输出如下:
* ------stateOut------- false
----stateEffect----- false
-----stateChange-------- false
------stateOut------- true
--------我点击了按钮-----
------stateOut------- true
----stateEffect----- true
------我执行了state------
*/
}, [count]);
可以看到初始值和进入Effect后值都为false,但是在调用setState方法更新过后打印出的值仍然是false,表明值没有被立刻更新,所以下面的In也没有打印出来。
但是在代码走完以后,它对值进行了更新且刷新页面并有一次输出了out,这时值为true,说明他是异步更新的,更新后会刷新页面。
在点击按钮后,触发更新生命周期,此时他的值仍然为被改后的true,且输出了我执行了state,表明他的值在页面刷新后仍然是可以被存储的,因此我们可以通过他的值得改变来记录生命周期过程中页面的状态。
但是他的弊端就是不能在更新后立刻拿到改变后的值。
useRef
通常用它来记录dom,但是他也可以保存值使用。
const ref = useRef(false);
console.log("------refOut-------", ref.current);
useEffect(() => {
console.log("----refEffect-----", ref.current);
if (ref.current) {
console.log("------我执行了ref------");
} else {
ref.current = true;
console.log("-----ref.currentChange--------", ref.current);
if(ref.current) {
console.log("------refIn-------", ref.current);
}
}
/**输出如下:
* ------refOut------- false
----refEffect----- false
-----ref.currentChange-------- true
------refIn------- true
--------我点击了按钮-----
------refOut------- true
----refEffect----- true
------我执行了ref------
*/
可以看到初始值和进入Effect后值都为false,但是在将ref.current的值更改过后,立马就可以得到它更改后的值,并输出了change,表明他的值是同步更新的,而且直接打印出了In。
在更新过程中也没有重新加载页面打印出out。
再点击按钮触发更新周期后,他的值仍然为true,并打印了我执行了,说明它可以横跨生命周期。
因此,当我们有一些逻辑或状态对值的更新要求较高,在值更新后就要立刻拿到并使用,有要求他跨生命周期,在页面更新后仍然保存值,就可以采用这种方法定义值。