在你崩潰之前,這8種做法會讓React應(yīng)用程序先崩潰
React庫的優(yōu)勢非常明顯:創(chuàng)建復(fù)雜的交互用戶界面非常簡單。最大的特點是可以在不破壞其他組件的情況下,將組件直接組合在一起。即使是Facebook、Instagram、Pinterest這樣的社交媒體巨頭也大量使用React,同時通過谷歌Maps這樣的大型API創(chuàng)造無縫的用戶體驗。
如果你正在用React構(gòu)建一個應(yīng)用程序,或是考慮將其用于即將開展的項目,那么本教程就是為你準(zhǔn)備的。希望通過公開一些需要再三考慮的代碼執(zhí)行,來幫助你構(gòu)建出色的React應(yīng)用程序。
下面是React里會使應(yīng)用程序崩潰的八種做法:
1. 在null上設(shè)置默認(rèn)參數(shù)
這是一個令人毛骨悚然的陷阱,可以讓開發(fā)人員全線崩潰。畢竟,應(yīng)用程序崩潰不是小事——任何類型的崩潰如果處理不當(dāng),隨時都可能導(dǎo)致資金損失。
比如:
在應(yīng)用程序組件中,如果日期最終是falsey,它將初始化為null。直覺告訴我們,在默認(rèn)情況下,當(dāng)項是一個falsey值時,應(yīng)該將其初始化為空數(shù)組。但是當(dāng)日期為falsey時,應(yīng)用程序會崩潰,因為條目為空。
如果沒有傳遞值或者未定義的值,那么默認(rèn)函數(shù)參數(shù)允許使用默認(rèn)值初始化已命名參數(shù)!
因此,下次將默認(rèn)值設(shè)置為null時,一定要三思而后行。當(dāng)空數(shù)組是值的預(yù)期類型時,可以將值初始化為空數(shù)組。
2. 用方括號抓取屬性
有時抓取屬性的方式可能會影響到應(yīng)用程序的行為。也就是說會造成應(yīng)用程序崩潰。下面是一個用方括號執(zhí)行對象查找的例子:
這些實際上都是100%有效的用例,除了比對象鍵查找慢之外,實際上沒有任何問題。無論如何,隨著查找的深入,應(yīng)用程序里也會出現(xiàn)問題:
如果你對此代碼段實施某些增強并犯了一個小錯誤(例如將j中的J大寫),結(jié)果將立即返回undefined,并且會發(fā)生崩潰:
令人毛骨悚然的部分是,應(yīng)用程序會直到一部分代碼嘗試使用未定義值進行屬性查找時才會崩潰。
所以在同一時間,joesProfile(經(jīng)過偽裝的未定義)將在應(yīng)用程序運行,沒有人會知道這個未定義值正在蔓延,直到一段代碼執(zhí)行屬性查找,如joesProfile.age,因為joesProfile未定義!
為避免崩潰,一些開發(fā)人員會在查找不成功時初始化一些默認(rèn)有效返回值:
至少現(xiàn)在,應(yīng)用程序沒有崩潰。這說明,當(dāng)你使用方括號表示法應(yīng)用查找時,往往是無效的。
然而,如果沒有實際的例子,很難解釋這種做法的嚴(yán)重性。所以,接下來我們舉一個真實的例子。以將要展示的這個代碼示例為例,它可以追溯到8個月前的存儲庫。為了保護這個代碼來源的一些隱私,我們重名了幾乎所有的變量,但是代碼設(shè)計、語法和架構(gòu)完全一樣:
fixVideoTypeNaming是一個函數(shù),它將根據(jù)作為參數(shù)傳入的值提取視頻類型。如果參數(shù)是一個視頻對象,它將從.videoType屬性中提取視頻類型。如果是字符串,則調(diào)用者傳入videoType,這樣就可以跳過第一步。有人發(fā)現(xiàn)視頻類型.mp4property在應(yīng)用程序的幾塊地方都被拼錯了。用fixVideoTypeNaming來快速修補這個錯誤。
現(xiàn)在,這個應(yīng)用程序是用Redux構(gòu)建的——因此語法。
要使用這些選擇器,你可以導(dǎo)入到connect高階組件中,以附加一個組件來偵聽狀態(tài)的那部分。
UI組件
該組件接收HOC傳遞給它的所有屬性,并顯示適應(yīng)屬性里的數(shù)據(jù)的信息。理想狀態(tài)下可行,現(xiàn)實中只是暫時可行。 如果回到容器中,看看選擇器是怎么選擇它們的值的,其實可能已經(jīng)埋下了一個定時炸彈,正在等著爆炸:
在開發(fā)任何類型的應(yīng)用程序時,為了確保較高的可信度和減少開發(fā)流程中的漏洞,一般在開發(fā)過程中進行測試,以保證應(yīng)用程序按預(yù)期運行。 然而,在這些代碼片段的案例中,如果沒有經(jīng)過測試,而且沒有及早處理,應(yīng)用程序就會崩潰。例如,state、app、media、video、videoType是鏈的四個層次。
如果一個開發(fā)人員在修復(fù)應(yīng)用程序的另一部分時不小心出錯了,而state、app、media、video變成未定義狀態(tài),那么應(yīng)用程序?qū)⒈罎?,因為它無法讀取未定義的videoType的屬性。
此外,如果videoType出現(xiàn)了另外一個錯誤,而fixVideoTypeNaming沒有更新以適應(yīng)mp3的問題,那么該應(yīng)用程序?qū)⒚媾R另一個意外崩潰的風(fēng)險。而這除非發(fā)生在真實的用戶身上,否則沒人能夠檢測到它。那時就為時已晚了。 絕不可以僥幸認(rèn)為應(yīng)用程序永遠不會碰到這樣的漏洞。請小心點!
3. 渲染時粗心地檢查空對象
在過去有條件地渲染組件的黃金時期,有人曾做過一件事,那就是檢查數(shù)據(jù)是否使用Object.keys填充到對象中。如果有數(shù)據(jù),那么如果條件通過,組件將繼續(xù)渲染。
假設(shè)調(diào)用了某個API,并在響應(yīng)的某個地方接收了作為對象的項。話雖如此,乍一看似乎完全沒有問題。項目的預(yù)期類型是對象,所以用Object.keys完全沒問題。畢竟,如果出現(xiàn)錯誤并轉(zhuǎn)化為falsey值,的確可以通過把項初始化為空對象來進行防御。
但服務(wù)器不總是返回相同的結(jié)構(gòu)。如果將來項變成數(shù)組會怎樣?Object.keys(items)不會崩潰,但會返回一個奇怪的輸出,比如[“0”、“1”、“2”]。被該數(shù)據(jù)渲染的組件該如何反應(yīng)呢?
但這還不是最糟的部分。代碼片段中最糟的是,如果屬性里收到的項是空值,那么項甚至不會初始化為默認(rèn)值。
那么在開始使用應(yīng)用程序前,就崩潰了:
再說一遍,請小心點!
4. 在渲染前粗心地檢查數(shù)組是否存在
這可能和第3條的情況非常相似,但是數(shù)組和對象經(jīng)??梢曰Q使用,所以應(yīng)該單列出來。
如果你有這樣做的習(xí)慣:
那么至少確保有單元測試,始終密切關(guān)注這段代碼,或者在傳遞給渲染函數(shù)前及早正確地處理arr,否則如果arr變成對象文字,應(yīng)用程序就會崩潰。當(dāng)然, &&操作符會認(rèn)為它是真實的,并嘗試.map對象文字,這最終導(dǎo)致整個應(yīng)用程序的崩潰。
所以請牢記于心。節(jié)省你的精力以及挫敗感,把它留給更值得你特別關(guān)注的大問題吧!
5. 沒有使用Linter
如果在開發(fā)應(yīng)用程序時,沒有使用任何類型的linter,或者根本不知道它們是什么,你必須知道為什么它們在開發(fā)中很有用。
用來輔助開發(fā)流程的linter是ESLint(https://eslint.org/?source=post_page---------------------------),這是一個著名的JavaScript的linting工具,它允許開發(fā)人員在不執(zhí)行代碼的情況下發(fā)現(xiàn)問題。
這個工具非常有用,它就像半個導(dǎo)師一樣,及時糾正錯誤——就好像有人在指導(dǎo)你一樣。它甚至描述了為什么你的代碼可能是錯誤的,并建議你應(yīng)該做什么。
這里有一個例子:
關(guān)于ESLint最酷的是,如果不喜歡某些規(guī)則或是不同意其中的一些規(guī)則,可以禁用這些規(guī)則,這樣它們就不會在開發(fā)時顯示為 linting警告/錯誤了。
6. 在渲染列表時進行解構(gòu)
過去有些人出現(xiàn)過這種情況,而且很難檢測到漏洞?;旧希绻幸粋€項目列表,并且準(zhǔn)備渲染每個項目的一堆組件,如果列表中有一個項目不是期待值,那么應(yīng)用程序會出現(xiàn)漏洞。如果應(yīng)用程序不知道如何處理值類型,就有可能會崩潰。
這里有一個例子:
代碼可以成功地運行。來看看API調(diào)用,而不是返回這個——
——如果在API客戶端出現(xiàn)了意外情況并且返回這個數(shù)組時,如何解決這個問題呢?
那么應(yīng)用程序就會崩潰,因為它不知道如何處理:
- Uncaught TypeError: Cannot read property 'name' of undefined
- at eval (DataList.js? [sm]:65)
- at Array.map (<anonymous>)
- at DataList (DataList.js? [sm]:64)
- at renderWithHooks (react-dom.development.js:12938)
- at updateFunctionComponent (react-dom.development.js:14627)
所以為了防止應(yīng)用崩潰,可以在每次迭代中都設(shè)置一個默認(rèn)對象:
現(xiàn)在,用戶不會再對你的技術(shù)和專業(yè)知識評頭論足了,因為他們不會再看到頁面崩潰的情況了:
然而,即使應(yīng)用不再崩潰,建議進一步處理缺失值,比如為具有類似問題的整個項目返回null,因為其中沒有任何數(shù)據(jù)。
7. 沒有充分研究你要實施的東西
不少人曾犯過這個致命的錯誤:對自己實施的搜索輸入過度自信,過早相信自己的觀點。
這是什么意思呢?搜索輸入這一部分本應(yīng)是個簡單的任務(wù)——而且的確如此。整個搜索功能出現(xiàn)問題的真正原因是在查詢中包含字符。
如果將關(guān)鍵字作為查詢發(fā)送到搜索API,僅僅認(rèn)為用戶鍵入的每個鍵是有效的是不夠的,即使是因為它們都在鍵盤上。
只要100%確保這樣的正則表達式完全按預(yù)期運行,并避免遺漏任何可能使應(yīng)用崩潰的無效字符:
該示例是搜索API最新的、既定的正則表達式。 以前它是這樣的:
可以看到斜杠/不見了,而這導(dǎo)致了應(yīng)用崩潰!如果該字符最終通過網(wǎng)絡(luò)發(fā)送到API,猜猜API會如何處理URL?
另外,不要完全相信在網(wǎng)上找到的例子。其中有許多都不是經(jīng)過充分測試的解決方案。而且就正則表達式而言,大多數(shù)用例沒有真正的標(biāo)準(zhǔn)。
8. 不限制文件輸入的大小
限制用戶選擇的文件大小是很好的做法,因為大多數(shù)情況下,如果不會出現(xiàn)任何品質(zhì)損失,可以對大文件進行壓縮。
但關(guān)于為什么把文件大小限制在某個限度內(nèi),還有一個更重要的原因。在公司里,用戶上傳圖片時偶爾會被“凍結(jié)”。并不是每個人都有Alienware 17 R5電腦,所以必須考慮用戶的特殊情況。
你不會希望用戶在本應(yīng)上傳文件的時候卻上傳電子游戲吧?
以下是將文件限制為5 MB(5,000,000字節(jié))限制的示例: