React 第二十一节 useDeferredValue 开发中用法注意事项
1、概述
useDeferredValue
是用于延迟渲染视图UI组件的,可以帮助我们管理视图渲染过程中的状态,并提高程序运行的性能;
2、用法
const deferredVal = useDeferredValue(params)
params
: 是我们需要延迟的数据;可以是任何类型的数据,可以是基础类型,也可以是引用类型;
deferredVal
:返回的延迟值
初始化渲染时候:useDeferredValue
返回的延迟值与 我们提供的值是一样的,
组件更新时候:React 先使用旧值进行 渲染,并且在后台使用 延迟值进行另一个线程渲染;
3、用途
多用于复杂的数据计算或者网络请求数据响应比较缓慢的场景中
;这样可以避免频繁的更新状态视图;
比如:长列表的搜索框,当用户每次输入关键字时候,我们都需要发起请求,同时更新状态,通过状态驱动视图重新渲染,这样会导致更新过于频繁,而影响渲染进程性能;
模拟10000条数据渲染;
// 父组件
import {Suspense, useState, useDeferredValue } from 'react'
import List from './List'
export default function MyDeferredValue() {
const [params, setParams] = useState('')
const deferredVal = useDeferredValue(params)
const handleChangeParams = (e) => {
setParams(e.target.value)
}
return (
<div>
<label>
搜索:
<input type="text" value={deferredVal} onChange={handleChangeParams} />
</label>
<p>deferredVal--{deferredVal}</p>
<p>params--{params}</p>
<Suspense fallback={<h2>loading...</h2>}>
<List params={params}></List>
</Suspense>
</div>
)
}
子组件监听 传入的 关键字params 进行数据过滤,当数据量大时候,发现params已最新值,而deferredVal 依旧是原值,此时视图依然保持原样,频繁输入时候,列表只会渲染最后一次输入的关键字;
import { useState, useEffect } from 'react'
export default function List({params}) {
console.log('=params==', params)
let data = []
const [dataArr, setDataArr] = useState([])
for (let i = 0; i < 10000; i++) {
data.push({
title: `名称${i+1}`,
id: i,
content: String(Math.random() * 100 )
})
}
useEffect(() => {
return () => {
let newData = data.filter(itm => (itm.title.indexOf(params) > -1 || itm.content.indexOf(params) > -1))
setDataArr([...newData])
}
}, [params])
return (
<div>
<ul>
{dataArr.map((item) => (
<li key={item.id}>{item.title}-{item.content}</li>
))}
</ul>
</div>
)
}
4、注意事项:
4.1、若我们需要延迟的数据是引用类型,并且每次组件更新时候都会创建一个新对象,并将新对象立即传递给 useDeferredValue,那么会因为引用对象的指向不一样,而导致视图每次都会重新渲染,这样就会增加不必要的渲染次数;
4.2、useDeferredValue 接收的值,每次都会使用Object.is() 进行对比,如果不一样,则会中断后台的视图渲染,进而使用新的延迟值 deferredVal 进行渲染;
4.3、useDeferredValue 本身不会阻止额外网络的请求;
4.4、useDeferredValue 本身并不会引起固定的延迟;在React 中只要当前渲染进程完成,React则会使用新的延迟值进行处理后台的重新渲染,
4.5、useDeferredValue 使用延迟值在后台完成的渲染,提交到前台屏幕视图时,不会触发Effect;而当后台渲染被中断时候,Effect 会咋子数据加载后后UI视图渲染后进行;
4.6、useDeferredValue 由于无法预知下次更新时间,可能是在很长的时间才能更新数据,这时可能组件已经卸载,那么就会导致 内存溢出 情况;
useDeferredValue 还提供了取消更新的函数;
const [params, setParams, cancelUpdate] = useDeferredValue(initvalue)
Effect(() => {
return () => {
// 取消延时更新函数
cancelUpdate()
}
}, [])
```
4.7、useDeferredValue 可以传入配置对象;
const [params, setParams] = useDeferredValue(initValue, {
timeoutMs: 500, // 延迟更新时间,单位毫秒
maximumTimeMs: 2000, // 最长延迟更新时间,单位毫秒
equalityFn: (a, b) => a.id === b.id, // 状态相等性比较函数
```
注:上述内容如果遗落错误,欢迎批评指正,大龄程序员正在寻找新的出路