前言
在开发的过程中,对state在函数取值,以及渲染的次数一知半解,了解了一部分关于state的内容,导致在使用上有些问题,因此写了几个案例,来全面的总结一下state的使用。
一.案例之前先总结一下关于state使用(react17之后)
- 在react的合成事件或者js原生事件操作state分为两种不同的情况
- 在同步函数或者异步函数中操作state分为两种不同情况
二.案例
下面分为四个案例,来分别查看在react操作state时的取值情况,以及渲染次数。
1.react合成事件中操作state
import React ,{useState} from "react";
export default function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
function handleClick() {
setCount(count+ 1);
console.log(count);
setCount(count+1);
console.log(count);
setFlag(f => !f);
}
console.log('render')
return (
<div>
<button onClick={handleClick}>Next</button>
<h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
</div>
);
}
点击一次的结果
从上面的结果看,在React合成事件中,同步操作下的结果看:
- 1.setCount两次,两次的count都为0,所以即便是serCount(count+1)两次,最终展示的结果是1
- 2.在引入了两个state,并进行了改变,最终渲染了一次
2.在JS原生事件中操作state
import React, {useEffect, useState} from "react";
export default function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
useEffect(() => {
document.getElementById('button').onclick= () => {
setCount(count + 1);
console.log(count)
setCount(count + 1);
console.log(count);
setFlag(!flag);
}
}, [])
console.log('render')
return (
<div>
<button id='button'>Next</button>
<h1 style={{color: flag ? "blue" : "black"}}>{count}</h1>
</div>
);
}
点击一次的结果 从上面的结果看,在原声操作下的结果看:
- 1.setCount两次,两次的count都为0,所以即便是serCount(count+1)两次,最终展示的结果是1
- 2.在引入了两个state,并进行了3次state改变,最终渲染了3次(结果图的第一行log的‘render’是初始化)
3.在异步函数中操作state
import React ,{useState,useEffect} from "react";
export default function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
useEffect(()=>{
setTimeout(()=>{
setCount(count+1);
console.log(count);
setCount(count+1);
console.log(count)
setFlag(f => !f);
})
},[])
console.log('render')
return (
<div>
<button>Next</button>
<h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
</div>
);
}
渲染结果 从上面的结果看,在异步函数操作下的结果看:
- 1.setCount两次,两次的count都为0,所以即便是serCount(count+1)两次,最终展示的结果是1
- 2.在引入了两个state,并进行了3次state改变,最终渲染了3次(结果图的第一行log的‘render’是初始化)
4.在React合成异步操作state
import React, {useState} from "react";
export default function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
async function handleClick() {
await setCount(count + 1);
console.log(count);
await setCount(count + 1);
await console.log(count)
setFlag(f => !f);
}
console.log('render')
return (
<div>
<button onClick={handleClick}>Next</button>
<h1 style={{color: flag ? "blue" : "black"}}>{count}</h1>
</div>
);
}
点击一次结果: 从上面的结果看,在合成事件异步函数操作下的结果看:
- 1.setCount两次,两次的count都为0,所以即便是serCount(count+1)两次,最终展示的结果是1
- 2.在引入了两个state,并进行了3次state改变,最终渲染了3次(结果图的第一行log的‘render’是初始化)
总结
- 在异步调用的前提下,state是同步的,每次改变都会触发渲染
- 在原声事件中,state是同步的,每次改变都会触发渲染
- 在合成事件中,state是异步的,在方法执行完之后进行渲染
思考:为什么state在不同的条件下的策略是不同的呢? 这个问题是关于react的性能优化机制,避免重复的渲染,通过批处理的方式来实现。