近期做tabs 切换时,发现由于useState 异步更新,导致tabs 显示的总是上一步的结果,简单记录一下解决方法。
一、 useEffect 解决
1. useState 介绍
useState是让函数组件可以定义自己的state
useState调用会返回一个数组, 分别是变量和改变变量的方法
useState需要接收一个参数,是变量的初始值
useState改变数据是异步的
2. useState 和 useRef 区别
3. 异步更新问题
如图,需要在切换tabs 时 显示对应的数据,但目前点击100米时,显示的是上一次点击的800米的数据,以下代码为点击tabs 的改变事件,
const onChange = (key: string) => {
// console.log('key》》',key);
// key, 切换tabs 的值
// newData, 切换tabs对应渲染的内容
if (key === 'longJump') {
setNewData(longJumpData)
}
if (key === 'solid') {
setNewData(solidData)
}
if (key === 'eightHundred') {
setNewData(eightHundredData)
}
if (key === 'oneHundred') {
setNewData(oneHundredData)
}
};
4. useEffect 介绍
useEffect用于处理副作用,代替生命周期
useEffect没有返回值,里面需要传入一个函数作为参数
如果useEffect里面只传入了一个函数,相当于类组件的componentDidMount和componentDidUpdate
useEffect还可以接收第二个参数,是一个数组(依赖数组)
如果第二个参数是空数组,相当于类组件的componentDidMount
如果第二个参数有内容,相当于vue的watch
如果第一个函数参数里面返回一个函数,相当于类组件的componentWillUnmount
useEffect(() => {
// getData().then((res) => {
// console.log(res);
// });
// todo 在useEffect里面使用async的方式请求封装好的接口,需要写函数自执行
(async () => {
const res = await getData();
console.log(res);
})();
}, []);
5. 用udeEffect 解决 useState 异步改变数据,数据更新不及时
useEffect(()=>{
if (current === 'longJump') {
setNewData(longJumpData)
}
if (current === 'solid') {
setNewData(solidData)
}
if (current === 'eightHundred') {
setNewData(eightHundredData)
}
if (current === 'oneHundred') {
setNewData(oneHundredData)
}
},[current])
// tabs 的切换事件,key/current-tabs切换后的key
const onChange = (key: string) => {
setCurrent(key)
};
二、 深拷贝解决
浅拷贝 基本类型之前互不影响,引用类型其中一个对象改变了地址,就会影响另一个对象; 改变新对象会使原数据一同改变
场景:添加数据,修改变量,页面更新不及时
错误写法:以下两种方法,其中一个是浅拷贝,引用了对象的地址,相当于两种都是修改了useState变量自身,用变量自身去push ,变量自身已经改变,再set时相当于没有变化,这个时候生命周期监听不到。
正确写法:深拷贝出来另一个数组 去改变数组 在set
import { cloneDeep } from 'lodash';
const handleOk = () => {
addFacilityForm.validateFields()
.then((values) => {
const newFacilityList = cloneDeep(facilityList);
newFacilityList.push(values)
setFacilityList(newFacilityList)
})
setIsModalOpen(false);
};