不同數(shù)據(jù)管理的意義
? ? state、redux等數(shù)據(jù)管理都有各自的意義,不要盲目使用state或redux
? ? 1. state:react是數(shù)據(jù)驅(qū)動(dòng)更新,state更新會(huì)重新觸發(fā)render進(jìn)行頁(yè)面更新,不要將與頁(yè)面更新無(wú)關(guān)的數(shù)據(jù)也存放在state中,state是驅(qū)動(dòng)數(shù)據(jù),不僅僅只是單純的數(shù)據(jù)概念
? ? 2.redux:redux主要是解決跨多層組件之間的數(shù)據(jù)共享,使用redux管理數(shù)據(jù)需要相關(guān)的reducer、action、connect、mapStateToProps/mapDispatchToProps等,不得不說(shuō)引入redux會(huì)使得代碼可讀性降低,在開(kāi)發(fā)中應(yīng)該盡量少使用redux管理數(shù)據(jù),對(duì)于跨越一兩層組件且共享組件較少的數(shù)據(jù)利用props傳遞更加方便快捷(見(jiàn)識(shí)過(guò)將所有數(shù)據(jù)放在redux中維護(hù)的組件,state幾乎都廢棄了)
? ? 3.Form.create():antd(下面所講特指3.x版本使用方法) Form組件提供的可獨(dú)立管理多個(gè)表單項(xiàng)數(shù)據(jù)的機(jī)制,能夠大大減少人工管理表單的變量與表單項(xiàng)數(shù)據(jù)處理邏輯,極力推薦,創(chuàng)建form實(shí)例通過(guò)props注入到組件中,靈活的getFieldDecorator方法可進(jìn)行零散的收集需要綁定的表單項(xiàng)(甚至可以跨越組件進(jìn)行收集綁定),在以大量表單為主的中后臺(tái)系統(tǒng)可以看作是另一種獨(dú)立的數(shù)據(jù)狀態(tài)管理器
組件封裝、模塊拆分
? ? ?這是很重要且有意義的,開(kāi)發(fā)中一定要注意避免大組件(數(shù)千行),合理對(duì)大組件進(jìn)行模塊拆分,不同模塊組件盡可能將各自功能內(nèi)聚,減少對(duì)外部的依賴(lài),父組件僅用來(lái)處理公共事件與子組件的交互即可
與組件實(shí)例無(wú)關(guān)或關(guān)聯(lián)教少的工具函數(shù)/教大靜態(tài)數(shù)據(jù)放在組件外部定義(當(dāng)組件復(fù)用時(shí)能減少代碼運(yùn)行體積)
數(shù)據(jù)解構(gòu)與賦值
? ? 避免直接使用 data.a.b.c.d 的方式直接讀取值,容易造成取值錯(cuò)誤而頁(yè)面崩潰。使用數(shù)據(jù)解構(gòu)時(shí)結(jié)合賦初始值來(lái)避免這種錯(cuò)誤(也可使用lodash.get):

&& || 與三目
某些場(chǎng)景使用邏輯運(yùn)算符 && 和 || 以及三目運(yùn)算符 替代if else 更簡(jiǎn)潔
語(yǔ)義化使用map、filter、reduce、some等函數(shù)
?語(yǔ)義化不僅僅只體現(xiàn)在html標(biāo)簽中,我們的所有代碼都應(yīng)具有相應(yīng)的語(yǔ)義,從語(yǔ)義化html標(biāo)簽、map等語(yǔ)義函數(shù),甚至到變量命名、組件模塊劃分、項(xiàng)目目錄規(guī)劃都應(yīng)在閱讀代碼時(shí)體現(xiàn)相應(yīng)語(yǔ)義
react中的key
合理改變key強(qiáng)制組件進(jìn)行刷新,可減少部分代碼邏輯
? ? 比如hooks中僅在創(chuàng)建時(shí)執(zhí)行一次的useState或者表單的初始值賦值(以props傳入的值作為初始值),這些初始值在組件更新期間并不會(huì)再次生效(即使依賴(lài)數(shù)據(jù)改變了),按正常操作,我們需要在componentWillReceiveProps或者在useEffect中監(jiān)聽(tīng)傳入的props依賴(lài)是否變化來(lái)對(duì)state數(shù)據(jù)或表單值進(jìn)行更改,另一種偷懶方法就是利用key的變化來(lái)強(qiáng)制組件重新進(jìn)行加載,當(dāng)依賴(lài)的props數(shù)據(jù)改變,在父組件中改變子組件key來(lái)強(qiáng)制子組件重新加載
可使用setTimeout將某些操作放入異步任務(wù)中延后執(zhí)行,在開(kāi)發(fā)中可以使用這個(gè)騷操作(少用)
? ? 注意在js中只有setTimeout與Promise回調(diào)才是真正意義上的異步事件,這些事件回調(diào)最終會(huì)放入瀏覽器渲染進(jìn)程下的事件觸發(fā)線(xiàn)程中去等待js引擎線(xiàn)程執(zhí)行完畢后再去輪詢(xún)執(zhí)行。
? ? 對(duì)于setState所說(shuō)的同步異步與上面所說(shuō)完全不是一回事,這里的異步只是react內(nèi)部實(shí)現(xiàn)的state批量更新機(jī)制,其實(shí)并不能稱(chēng)為異步,只是給我們的感覺(jué)像是異步。
React數(shù)據(jù)驅(qū)動(dòng)概念
?把這兩個(gè)詞拆開(kāi)來(lái)理解:數(shù)據(jù)與驅(qū)動(dòng)
?React中進(jìn)行驅(qū)動(dòng)的數(shù)據(jù)容易想到的是state,當(dāng)然也包含props;驅(qū)動(dòng)可以理解為觸發(fā)render進(jìn)行頁(yè)面更新渲染。后者是框架自動(dòng)實(shí)現(xiàn)的,所以React開(kāi)發(fā)中的關(guān)注點(diǎn)是數(shù)據(jù)。
? ? 一個(gè)組件在首次進(jìn)行加載時(shí)會(huì)走一遍render,再之后該組件實(shí)例的state與props更改都會(huì)觸發(fā)render,但state與props的改變并不一定會(huì)觸發(fā)組件的render,因?yàn)镽eact為了降低對(duì)前后數(shù)據(jù)比對(duì)的性能開(kāi)銷(xiāo)采取了數(shù)據(jù)的淺比對(duì),僅對(duì)前后state或前后props數(shù)據(jù)的第一層進(jìn)行淺比較,所以可以進(jìn)一步理解為是state與props數(shù)據(jù)對(duì)象中的第一層屬性數(shù)據(jù)的在驅(qū)動(dòng)React組件的更新
state更改
react不建議直接修改state,開(kāi)發(fā)中如果直接修改state容易造成bug(特指手動(dòng)修改嵌套層次較深的state數(shù)據(jù)),要注意繼承PureComponent的組件由于重寫(xiě)了SCU,會(huì)對(duì)state與props進(jìn)行淺比對(duì)可能會(huì)導(dǎo)致SCU返回false而不進(jìn)行頁(yè)面更新,如果手動(dòng)修改了state在setState時(shí)需重新申明新數(shù)組或?qū)ο筮M(jìn)行數(shù)據(jù)更新才能觸發(fā)頁(yè)面更新:

大表單數(shù)據(jù)收集
? ? 開(kāi)發(fā)場(chǎng)景:在開(kāi)發(fā)中后臺(tái)應(yīng)用時(shí),常常會(huì)有收集和回填大表單的需求,新建一個(gè)任務(wù)時(shí)會(huì)有很多表單數(shù)據(jù)需要收集,而且此數(shù)據(jù)不僅僅限于form等表單項(xiàng),還可能是其它控件:Table中的數(shù)據(jù),而且對(duì)于大表單往往需要將模塊進(jìn)行拆分,在最終收集數(shù)據(jù)時(shí)需要收集各個(gè)模塊中的數(shù)據(jù),如何組織代碼邏輯能夠高效進(jìn)行各模塊的數(shù)據(jù)收集匯總,我通常有兩種方式:1. 通過(guò)ref;2.通過(guò)自定義表單控件;
? ? 1.通過(guò)ref:每個(gè)子表單組件模塊維護(hù)各自的表單數(shù)據(jù),每次表單控件值改變時(shí)將最新的表單值匯總到該組件state中進(jìn)行保存,定義一個(gè)獲取并返回該模塊所有表單數(shù)據(jù)的函數(shù),該函數(shù)本組件并不調(diào)用,而是提供給父組件利用ref來(lái)獲取該子模塊的表單數(shù)據(jù),這樣在提交整體大表單時(shí)父組件可利用ref獲取每一個(gè)子表單組件的數(shù)據(jù)進(jìn)行匯總處理。這種方法在父組件獲取各個(gè)子表單數(shù)據(jù)時(shí)特別簡(jiǎn)單粗暴。
? ? 2.通過(guò)自定義表單控件:這種方式基于antd的Form.create()(FormComp)高階組件,F(xiàn)orm.create創(chuàng)建了一個(gè)獨(dú)立的form實(shí)例用來(lái)管理使用getFieldDecorator()綁定的表單控件(或者自定義表單控件),其重寫(xiě)了表單控件的onChange事件,并結(jié)合每個(gè)表單控件的value實(shí)現(xiàn)了form實(shí)例與各表單控件的雙向綁定(form實(shí)例可利用setFieldsValue一系列api改變各個(gè)表單控件的value,另一方面每個(gè)表單控件的改變觸發(fā)onChange也會(huì)改變form實(shí)例內(nèi)保存的相應(yīng)表單控件的value)?;谝陨咸匦?,我們只需將在父組件中通過(guò)Form.create創(chuàng)建的form實(shí)例提供的getFieldDecorator分發(fā)到各個(gè)子表單模塊中就能自動(dòng)完成對(duì)所有子表單數(shù)據(jù)收集,在提交時(shí)利用form.getFieldsValue就能獲取到所有的表單數(shù)據(jù)。這種方式的優(yōu)勢(shì)在于一旦完成各表單項(xiàng)綁定,收集與校驗(yàn)邏輯在表單控件改變時(shí)就自動(dòng)完成了。
數(shù)據(jù)請(qǐng)求延遲的bug與useEffect中的函數(shù)防抖失效原因
場(chǎng)景:對(duì)于帶有多個(gè)篩選條件的Table,當(dāng)條件改變時(shí)就發(fā)送request請(qǐng)求table數(shù)據(jù),但有時(shí)由于網(wǎng)絡(luò)延遲會(huì)使得先請(qǐng)求的request返回?cái)?shù)據(jù)較晚,導(dǎo)致渲染的table數(shù)據(jù)不正確
解決方法:使用hook的useEffect監(jiān)控篩選條件的改變,當(dāng)條件改變時(shí)去就發(fā)送請(qǐng)求,為了緩解間隔較短的多次請(qǐng)求因網(wǎng)絡(luò)延遲造成拿不到最后一次請(qǐng)求的數(shù)據(jù),將useEffect內(nèi)部執(zhí)行的request函數(shù)做下防抖
tip: 防抖只能緩解由于網(wǎng)絡(luò)延遲造成的bug,即使在網(wǎng)絡(luò)狀況良好情況下,加上防抖也可以減少不必要的請(qǐng)求,也是一種優(yōu)化


useCallback與useMemo
? hooks中使用useCallback與useMemo對(duì)數(shù)據(jù)與函數(shù)進(jìn)行緩存,避免在給子組件傳遞數(shù)據(jù)與函數(shù)時(shí)造成子組件無(wú)謂刷新

