網站首頁 編程語言 正文
react中列表渲染的局部刷新
最近在寫demo的時候遇到一個更新列表中某個的對象的某個值,最期待的結果肯定是局部刷新,但是我們往往在改變值之后會遇到全局都刷新的問題,以下為個人實驗出來的一個小技巧。
首先我有以下數據需要通過react的列表方法渲染:
let list=[
? ? {
? ? ? ? id:1,
? ? ? ? show:false
? ? },
? ? {
? ? ? ? id:2,
? ? ? ? show:false
? ? },
? ? {
? ? ? ? id:3,
? ? ? ? show:false
? ? }
]
我們通過以下react方法進行渲染:
render(){
? ? return (
? ? ? ? {list.map((val)=>{
? ? ? ? ? ? <DemoComponent val={val}/>
? ? ? ? })}
? ? )
}
在這里我們需要重新寫一個DemoComponent的組件:
import React,{Component} from 'react';
export class DemoComponent extends Component{
? ? render(){
? ? ? ? <div>
? ? ? ? ? <div>this.props.val.id</div>
? ? ? ? ? <button onClick={()=>this.toggleDialog()}>toggle</button> ?
? ? ? ? </div>
? ? }
? ? toggleDialog(){
? ? ? ? // 更改val.showDialog相關操作。
? ? }
? ? shouldComponentUpdate(nextProps){
? ? ? ? return JSON.stringify(nextProps) !== JSON.stringify(this.props);
? ? }
}
當我們點擊第一個button,這個時候就能達到局部刷新,只刷新第一個DemoComponent組件的效果了。
但以上操作是什么原理呢?
首先,大家平時都推薦使用的PureComponent不能在這里使用,因為這個組件沒有shouldComponentUpdate這個鉤子函數,雖然PureComponent也有對比props和nextProps并自行判斷當前組件是否需要重新渲染的功能,但是這個對比對對象是沒有用的,因為{} === {}是返回false的(對這個知識點不理解的朋友可以去看看堆棧相關的知識),數組同理。
那么為了讓其他列表組件沒有必要多去render一次,所以我在shouldComponentUpdate中取了個巧,直接JSON.stringify,將兩個對象轉換成字符串進行比較,這樣就方便的多。
當然這里也是自己為了不去寫一個isEqual方法而偷懶的做法,這樣做的好處是簡單方便,也節省時間(isEqual方法必然會for-in循環,對于更復雜的情況甚至需要遞歸,在內存消耗和時間復雜度上肯定會比JSON.stringify嚴重),缺點在于可拓展性不高,如果是個數組,就比較頭疼。?
react實現實時/局部刷新
在React項目中,經常會遇到諸如:刪除某一行的同時同時刷新表格展示最新的表格,而不是刪除后,手動刷新。
原先是在刪除時再次調用生命周期函數中展示表格列表的函數,但會影響性能。
總結:通過JS數組修改usestate中的狀態。
初始做法示例
useEffect(() => {
? ? ? ? httpOffer()
? ? }, [])
//獲取列表
? ? const httpOffer = () => {
? ? ? ? offerList()
? ? ? ? ? ? .then(res => {
? ? ? ? ? ? ? ? // console.log('offer', res)
? ? ? ? ? ? ? ? if (res.status === 200) {
? ? ? ? ? ? ? ? ? ? if (res.data.code === 0) {
? ? ? ? ? ? ? ? ? ? ? ? const data = res.data.data
? ? ? ? ? ? ? ? ? ? ? ? data.length > 0 && data.forEach(el => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? el.key = el.id
? ? ? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? ? ? setOffers(data)
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? message.error(res.data.msg)
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? message.info('network failed')
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? setLoading(false)
? ? ? ? ? ? })
? ? ? ? ? ? .catch(err => {
? ? ? ? ? ? ? ? setLoading(false)
? ? ? ? ? ? ? ? throw err
? ? ? ? ? ? })
? ? }
const showModalDel = (id) => {
? ? ? ? delOffer({ id })
? ? ? ? ? ? .then(res => {
? ? ? ? ? ? ? ? if (res.status === 200) {
? ? ? ? ? ? ? ? ? ? if (res.data.code === 0) {
? ? ? ? ? ? ? ? ? ? ? ? //之前的做法,刷新頁面
? ? ? ? ? ? ? ? ? ? ? ? httpOffer()
? ? ? ? ? ? ? ? ? ? ? ? message.info(res.data.msg)
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? message.error(res.data.msg)
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? message.error('Network failed!')
? ? ? ? ? ? ? ? }
? ? ? ? ? ? })
? ? ? ? ? ? .catch(err => {
? ? ? ? ? ? ? ? throw err
? ? ? ? ? ? })
? ? }
目前可以使用JS數組和usestate進行同樣的操作。
增加數據
addOffer(params)
? ? ? ? ? ? ? ? .then(res => {
? ? ? ? ? ? ? ? ? ? if (res.status === 200) {
? ? ? ? ? ? ? ? ? ? ? ? if (res.data.code === 0) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? let data = res.data.data
? ? ? ? ? ? ? ? ? ? ? ? ? ? //重點
? ? ? ? ? ? ? ? ? ? ? ? ? ? setOffers([...offers, { key: data.id, id: data.id, ...params}])
? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? message.info(res.data.msg)
? ? ? ? ? ? ? ? ? ? ? ? ? ? setVisible(false)
? ? ? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? message.error(res.data.msg)
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? message.error('Network failed!')
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .catch(err => {
? ? ? ? ? ? ? ? ? ? console.log(err)
? ? ? ? ? ? ? ? })
修改數據
editOffer(params)
? ? ? ? ? ? ? ? .then(res => {
? ? ? ? ? ? ? ? ?? ??? ??? ?//重點
? ? ? ? ? ? ? ? ? ? ? ? ? ? setOffers(offers.map(item => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(item.id === params.id){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.id = params.id,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.adv_id = params.adv_id,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return item
? ? ? ? ? ? ? ? ? ? ? ? ? ? }))
? ? ? ? ? ? ? ? ? ? ? ? ? ? setVisible(false)
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .catch(err => {
? ? ? ? ? ? ? ? ? ? console.log(err)
? ? ? ? ? ? ? ? })
刪除數據
const showModalDel = (id) => {
? ? ? ? delOffer({ id })
? ? ? ? ? ? .then(res => {
? ? ? ? ? ? ? ? ?//重點
? ? ? ? ? ? ? ? ?setOffers(offers.filter(item => item.id != id ))
? ? ? ? ? ? ? ? ?message.info(res.data.msg)
? ? ? ? ? ? })
? ? ? ? ? ? .catch(err => {
? ? ? ? ? ? ? ? throw err
? ? ? ? ? ? })
? ? }
原文鏈接:https://blog.csdn.net/ConanZzz_/article/details/90114736
相關推薦
- 2022-07-14 Oracle中nvl()和nvl2()函數實例詳解_oracle
- 2023-10-16 使用elemnt移動端字體大小會自動變小
- 2023-03-16 python中split()函數的用法詳解_python
- 2022-02-17 docker容器內的數據存放在哪里
- 2022-11-20 Python必知必會之os模塊實例詳解_python
- 2022-06-29 一文教會你使用Nginx訪問日志統計PV與UV_nginx
- 2022-02-19 小程序監聽屏幕滾動 判斷滾動方向上下滾動且滾動到一定位置
- 2022-07-30 Linux常見命令-搜索查詢類,find 查找文件或者目錄,locate 快速定位文件路徑,grep
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支