React 文檔導讀 — 克服文檔中難懂卻有趣的用法吧!
本文站在初入React世界的新手,總結一些「不適應」或是有點「不明白」的文檔上範例,作為導讀,搭配官方文檔服用。
「用藥須知」
希望你是一個已經勇敢打開並看過文檔的人,而不是一開始就直接觀看別人總結的二手知識。作為導讀,目前依照v16.8.4的文檔順序,如果未來重大版本更新,請自行忽略舊有的API。
「用途」
作為一個優秀的開源UI函式庫,其文檔當然是相當優秀,中文的翻譯也是隨手 Google就能查到,這篇主要解釋新手會覺得「有點不適應」的部分。
「目錄」
- 新手怎麼練習文檔上的用法?
- JSX、HTML、React Element?
- Class 組件傳 this 到底在 bind 什麼鬼?
- setState 解構 state 物件到底在…?
- 父子兄弟姐妹組件溝通不良?
怎麼使用、練習 React?
Add React to a Website 文檔中提到幾個方法,比如使用CDN將 React 加入網頁中,並且透過在 ReactDOM.render
傳入根節點
// ... the starter code you pasted ...
const domContainer = document.querySelector('#like_button_container');
ReactDOM.render(e(LikeButton), domContainer);
這邊我先建議你不要這麼做,這樣寫起來會比你想象中的克難十多倍。
這邊建議使用官方提供的 CRA(Create-react-app)連結,官方準備的 boilerplate ,搭配的 React、ReactDOM 都會是最新且穩定的版本,而且已經幫你配置好了 Webpack。
你可以專注於練習React,而非花太多時間自己配置Webpack、Babel、JSX、Polyfill、打包然後放棄。
這裡推薦另外一個讓你更快開始寫React的地方 — CodeSandbox,選擇 React 專案後就可以在 Web 上直接撰寫 React App 。
在 JS 裡面寫HTML好酷喔!但我搞不清楚什麼時候是HTML?
React 使用名叫做 JSX 的東西,儘管你在 vscode 、 codesandbox ,看到程式碼裡頭有 html 並且依照標籤高亮…但它並不是真正的 HTML。
const FirstComp = ()=>{
return <p className="greeting"> Hello! </p>
}
(↑ 這是你在編寫程式碼時看到的)
(記得 class 要改成 className 、for 改成 htmlFor…思考一下為什麼吧!)
const FirstComp = ()=>{
return {
type:'p',
{ className:'greeting' },
'Hello!
}
}
(↑ 經過Webpack的babel轉譯之後)
所以你寫的那坨看似 HTML 的東西,其實是仰賴於許多人的努力喲!
- babel — 針對像是HTML的東西拿去解析並且轉譯成這個樣子
- React — 把這坨物件最終給渲染成真實節點 (
createElement
)
(props在幹嘛…event在幹嘛…這些自己去看)
props 就是 property 嘛!可以想象成組件對外的接口。就像函數吃參數一樣,組件也要能夠有可以吃的東西嘛,就是props。
<Comp isGoodToDrink={20}/>// Comp.jsx
export (props)=>{
return <p> Drink = {props.isGoodToDrink} </p>
}
Class組件好難喔?為什麼常常 this 會報錯?為什麼傳setter給子組件要特別bind啊?
你有兩個選擇:
一、 搞懂 JavaScript 的 this 用法,搞懂在 Class 裡頭什麼時候是實例,箭頭函數、bind在幹嘛。
《JavaScript 的 this 到底是什麼?不懂 this 正在綁定的對象,連框架都難以使用…》
二、 完全放棄在 JavaScript 使用 this,所有會碰到 this 的狀況都避免掉,使用箭頭函數、使用函數組件。
使用 React-Hooks 管理你的函數組件裡頭的狀態。
setState 裡頭的解構
在第一次觀看React文檔時,對於setState的用法一定是各種懵逼,讓我們來看看最傳統的類組件 — Class Component。
有時候我們的類組件狀態是長這個樣子:
this.state = {
title : 'I am title',
height:400,
width: 300,
blablabla: {
xxx:20,
....
}
}
這種時候你要更新 title 的時候…必須要用setState,而且不能影響到其他的狀態嘛!
你總不希望更新完 title
之後結果狀態變成這樣
this.state = {
title: 'I am change'
}
所以 React 在這裡給了一個很給力的做法,只更新你想更新的狀態:
const obj = { title:'I am change' }
this.setState( prevState => Object.assign({}, prevState, obj))// obj 跟 prevState 一起被assign到空物件裡頭,產生一個新的物件
有時候你會看到像是這樣子的:
const obj = {name:'title', value:'I am Change'}
this.setState(prev=>Object.assign({},prev,{
[obj.name] : obj.value
}))
用這個像是陣列的框框把變數框住,之後就會變成 key 了。
const obj = {name:'title', value:'I am Change'}
Object.assign({},{ [obj.name] : obj.value })// {title:'I am Change'}
更多詳細的物件、陣列解構請看這篇 —《 解構賦值 — 設計函數時的小技巧》
欸幹,我發現子組件的值沒辦法丟上來欸?
在UI框架裡頭最常被問的就是這個問題,不管你是在Vue還是React都會碰到,單向資料流就是會有這個問題。
Ans. 請你把狀態拉伸到父組件,再把操作狀態、操作一堆狀態的函數丟下去。
記得!如果你用Class Component,要注意 this 。
我要傳父組件跟兒子的兒子的兒子溝通怎麼辦?
Ans. 幾個給你參考的答案
- 透過 Props 一路把操作狀態的函數向下傳遞,state定在最上面。
- 遇到這個狀況,代表你已經遇到狀態管理的問題,可以看看 Redux 。
- 透過 React 原生的 Context API 包覆 Provider 跨組件溝通
- Context API
- 我寫的廢文 —《 Context API — Props 傳送門》
尾聲
這篇文章不是那種 React 原始碼深度解析的高深文,而是統整當初認為有點複雜以及現在認為應該早點明白的概念。
希望這篇文章有幫助到你。