關(guān)于react中列表渲染的局部刷新問題
react中列表渲染的局部刷新
最近在寫demo的時候遇到一個更新列表中某個的對象的某個值,最期待的結(jié)果肯定是局部刷新,但是我們往往在改變值之后會遇到全局都刷新的問題,以下為個人實驗出來的一個小技巧。
首先我有以下數(shù)據(jù)需要通過react的列表方法渲染:
let list=[ ? ? { ? ? ? ? id:1, ? ? ? ? show:false ? ? }, ? ? { ? ? ? ? id:2, ? ? ? ? show:false ? ? }, ? ? { ? ? ? ? id:3, ? ? ? ? show:false ? ? } ]
我們通過以下react方法進(jìn)行渲染:
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相關(guān)操作。 ? ? } ? ? shouldComponentUpdate(nextProps){ ? ? ? ? return JSON.stringify(nextProps) !== JSON.stringify(this.props); ? ? } }
當(dāng)我們點擊第一個button,這個時候就能達(dá)到局部刷新,只刷新第一個DemoComponent組件的效果了。
但以上操作是什么原理呢?
首先,大家平時都推薦使用的PureComponent不能在這里使用,因為這個組件沒有shouldComponentUpdate這個鉤子函數(shù),雖然PureComponent也有對比props和nextProps并自行判斷當(dāng)前組件是否需要重新渲染的功能,但是這個對比對對象是沒有用的,因為{} === {}是返回false的(對這個知識點不理解的朋友可以去看看堆棧相關(guān)的知識),數(shù)組同理。
那么為了讓其他列表組件沒有必要多去render一次,所以我在shouldComponentUpdate中取了個巧,直接JSON.stringify,將兩個對象轉(zhuǎn)換成字符串進(jìn)行比較,這樣就方便的多。
當(dāng)然這里也是自己為了不去寫一個isEqual方法而偷懶的做法,這樣做的好處是簡單方便,也節(jié)省時間(isEqual方法必然會for-in循環(huán),對于更復(fù)雜的情況甚至需要遞歸,在內(nèi)存消耗和時間復(fù)雜度上肯定會比JSON.stringify嚴(yán)重),缺點在于可拓展性不高,如果是個數(shù)組,就比較頭疼。
react實現(xiàn)實時/局部刷新
在React項目中,經(jīng)常會遇到諸如:刪除某一行的同時同時刷新表格展示最新的表格,而不是刪除后,手動刷新。
原先是在刪除時再次調(diào)用生命周期函數(shù)中展示表格列表的函數(shù),但會影響性能。
總結(jié):通過JS數(shù)組修改usestate中的狀態(tài)。
初始做法示例
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數(shù)組和usestate進(jìn)行同樣的操作。
增加數(shù)據(jù)
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) ? ? ? ? ? ? ? ? })
修改數(shù)據(jù)
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) ? ? ? ? ? ? ? ? })
刪除數(shù)據(jù)
const showModalDel = (id) => { ? ? ? ? delOffer({ id }) ? ? ? ? ? ? .then(res => { ? ? ? ? ? ? ? ? ?//重點 ? ? ? ? ? ? ? ? ?setOffers(offers.filter(item => item.id != id )) ? ? ? ? ? ? ? ? ?message.info(res.data.msg) ? ? ? ? ? ? }) ? ? ? ? ? ? .catch(err => { ? ? ? ? ? ? ? ? throw err ? ? ? ? ? ? }) ? ? }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
React-Hook中使用useEffect清除定時器的實現(xiàn)方法
這篇文章主要介紹了React-Hook中useEffect詳解(使用useEffect清除定時器),主要介紹了useEffect的功能以及使用方法,還有如何使用他清除定時器,需要的朋友可以參考下2022-11-11antd?table動態(tài)修改表格高度的實現(xiàn)
本文主要介紹了antd?table動態(tài)修改表格高度的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07React前端解鏈表數(shù)據(jù)結(jié)構(gòu)示例詳解
這篇文章主要為大家介紹了React前端解鏈表數(shù)據(jù)結(jié)構(gòu)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10