最近在使用 React 進行開發時,發現了一個容易被忽視的細節,特此分享。
在使用函數組件時,我們通常會定義一些 props,但要注意在傳參的時候存在一些潛在的問題。
例子#
讓我們來看一個函數組件:
const OneSearch = (query, engine) => {
...
}
export default OneSearch;
在引用這個組件時,可能會這樣寫:
<OneSearch query={oneSearchQuery} engine={engine}></OneSearch>
表面上看起來一切正常,但如果仔細觀察函數組件的定義,會發現一個小小的細節,就在傳參的地方:(query, engine)
實際上,我們希望應該是這樣:({ query, engine })
為什麼呢?因為在 React 中,組件的參數是作為一個 JavaScript 對象傳遞的。在定義函數組件時,我們可以將參數寫作 (props)
或者其他任何名字,比如 (cop)
。而在引用組件時,JSX 會將傳遞的參數名和值打包成一個 JavaScript 對象,作為實參傳遞給組件。props
只是一個約定俗稱的名字,你可以通過這個名字來訪問傳遞過來的參數。
另一種寫法是 ({ query, engine })
,此時形參變成了一個對象,而 JavaScript 語法允許你通過這種形式直接訪問對象中的屬性。
但是,如果你採用 (query, engine)
這種寫法,情況就不同了。query
作為第一個形參,實際上接受的是一個 React 打包的對象,長這樣:
{
query: ...,
engine: ...
}
而且!這樣子寫是不會報錯的,因為 JS 裡的函數,調用參數無論傳夠了還是沒夠,甚至是多了,JavaScript 都不報錯。(至少在主流瀏覽器實現上是這樣)
這種逆天寫法,換其他語言早就開始叫了,Python 會在運行時爆個 TypeError,編譯型語言像 C/C++ 沒等你運行編譯器就先開始叫喚了,編譯都過不去。
但 JavaScript 允許這種行為發生而沒有任何提示!你參數傳多了,就會按照實參的順序依次給到形參(如果調用時沒有指定哪個實參要給到哪個形參的話),剩下的就不管;你傳少了,還是這樣。函數裡面要是引用沒給到實參的形參怎麼辦?那麼你引用的那個形參的值就是undefined
,沒了。就一個undefined
,甚至警告都不會有。
總結#
因此,在定義 React 組件時,建議採用 (props)
或者 ({ prop1, prop2 })
的形式,以避免潛在的問題。