Javascript在紅什麼?快跟著網頁設計小白🙆♀一起速速了解JS吧!
這篇文章專給…
- 彷彿聽過,對JS 似曾相似,但從來沒有真正了解
- 愛用Google analytics & inbound marketing (Hubspot) 的行銷人
- 覺得跟前端工程師錯頻,想了解一下他們星球的語言
- 想學互動式網頁設計,創建屬於自己的第一個網頁天堂
上次最後提到了 React hooks 的優缺和功用 ,也賣了好多關子,這次趁著「 JS 學習筆記」系列的終結篇的機會讓小白🙆♀把剩餘的 React JS 的核心觀念補上&好好說明白
如果忘記 hooks 的概要的小小白們在繼續閱讀之前可以先看回去上一篇👆
總的來說,hooks 並不會取代我們原先對於 React 的認知,而是(向後)相容於原先的系統中。原先系統(包括 props, state, refs, lifecycle 等概念)也能透過 hooks 所提供的「更直接性的」API 來同時達成效率 (efficiency)&簡化 (simplification)。
📌 話說從前,什麼又是 React 的生命週期 (Lifecycle) 呢?
正在學 React 想必都聽過「Lifecycle」,但許多人卻不解其意。
單就名字看來,「生命週期」一詞非常的「生物」(彷彿回到高中生物課😂)。實際上,的確如此。簡單來說,Lifecycle 所指的生命之期即是 React component 的一生:從出生入死中的酸甜苦辣。廢話不多說,就讓我們繼續看下去吧!
🦚 往往程式語言在命名上都十分傳神(如同 lifecycle 至少也有七八分到位),有人猜到我想講的例子嗎?
Overall, React 的生命週期分成三大階段:掛載 => 更新 => 卸載
以下圖示給大家欣賞(會說欣賞是因為大多小白應該都和我一樣有看沒有懂🙃)
(概要版,呈現大觀念)
(細節版,寫出所有相關細項)
這張圖應由上往下看👇&由左往右看👉
首先,第一步: 掛載 Mounting — 表示初載入進DOM
流程:(對照上圖)
constructor() 執行
getDerivedStateFromProps()
render() 渲染
componentDidMount()
📎 componentDidMount() 示範:
class Header extends React.Component { constructor(props) { super(props); this.state = {bestplace: "Taiwan"}; } componentDidMount() { setTimeout(() => { this.setState({bestplace: "Taipei"}) }, 1000) } render() { return ( <h1>The best place in the world is {this.state.bestplace}</h1> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
🦖 恐龍君小補充:
(a.)「render」是必要的流程!
(b.) 必須在最上層呼叫 hook,這樣 hooks 才會知道它該返回什麼
NG 作法:在迴圈、判斷式、或是嵌套 function 中呼叫 Hook
(c.) Hooks 只在 React function 或是自定義中 hook 調用
NG 作法:在普通的 JS 函式中
再來,第二步: 更新 Updated — 重新render
凡是 state 或 props 有改變,component 就必須重新渲染
流程:(對照上圖)
getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
📎 shouldComponentUpdate() 示範:(以下回傳 true 或 false 都可以隨需求自由變換)
class Header extends React.Component { constructor(props) { super(props); this.state = {bestplace: "Taiwan"}; } shouldComponentUpdate() { return false; } changePlace = () => { this.setState({bestplace: "Taipei"}); } render() { return ( <div> <h1>The best place in the world is {this.state.bestplace}</h1> <button type="button" onClick={this.changePlace}>Change place</button> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
📎 componentDidUpdate() 示範:
class Header extends React.Component { constructor(props) { super(props); this.state = {bestplace: "Taiwan"}; } componentDidMount() { setTimeout(() => { this.setState({bestplace: "Taipei"}) }, 1000) } componentDidUpdate() { document.getElementById("mydiv").innerHTML = "The best updated place is " + this.state.bestplace; } render() { return ( <div> <h1>The best place in the world is {this.state.bestplace}</h1> <div id="mydiv"></div> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
最後,第三步: 卸載 Unmounted —移出真實的DOM
流程:(對照上圖)
componentWillUnmount()
📎 componentWillUnmount() 示範:
class Container extends React.Component { constructor(props) { super(props); this.state = {show: true}; } delHeader = () => { this.setState({show: false}); } render() { let myheader; if (this.state.show) { myheader = <Child />; }; return ( <div> {myheader} <button type="button" onClick={this.delHeader}>Delete Header</button> </div> ); } } class Child extends React.Component { componentWillUnmount() { alert("The component named Header is about to be unmounted."); } render() { return ( <h1>Hello Iris!</h1> ); } } ReactDOM.render(<Container />, document.getElementById('root'));
🦖 恐龍君小補充:
- component 有兩種更新方式:setState&forceUpdate
- component 會隨父 component 的更新而更新(繼承,由上而下的資料流)
📌 上次簡單說明了 useState,那什麼又是 useEffect 呢?
我整理了下列 3 點,讓小小白們一次看明白:
- useEffect 是個專用於封裝 side effects (或 effects) 的 hook,這樣才能有效分工,使關注點成功分離
- 也可以把 useEffect 想成 componentDidMount &componentDidUpdate 和componentWillUnmounted 的綜合體,但切記仍是不一樣的概念。
- useEffect 讓 functional component 也能介入 React 的 lifecycle,使 React 清楚 component 在渲染後要做些什麼,並且在 DOM 更新後幫助你呼叫先前你傳遞的函式。
如果使用傳統的生命週期函式,需要如以下表達(以下為 React 官網範例):
componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; }
使用了 useState 就能簡化以上步驟(不需要考慮在更新或掛載階段),達到以上兩個生命週期函式的功效(API 的整合),我們來看看如何操作:
useEffect(() => { document.title = `You clicked ${count} times`; });
🦖 恐龍君小補充:
(a.) useEffect 和 componentDidMount 或是 componentDidUpdate 的不同在於由 useEffect 調動的 effect 不阻塞瀏覽器渲染與更新,因此以「效率」論是更有 CP 值得做法
(b.) useEffect 在每次渲染後都會執行(首次渲染和每次更新都會執行)
(c.) 使用完的 useEffect 視情況清除,想深入點這裡
這是 React JS 的最後一集介紹了,歡迎大家留言大聲喊出還想知道哪些 React 或是 JS 功能~ 有許願就有可能會成真唷!(我這邊會盡量加油🤣
這裡先拜過我的恩師Glove🙇♀
🎏 如果想更加了解 React JS 的「生命週期」,或是想更加了解「渲染」的人,這裡擺上 Glove 親筆部落格,非常建議和我一樣的小菜雞🐥上去爬個文~
Glove 另外也有在 Udemy 上開設 JS 課程 和 React 課程唷,特別適合唷想快速練功的人😎!(中文教學)🎏
之前是大菜雞🐥時認為說 Github 是個非常困難的地方(高手雲集,看都看不懂),不過仔細看過發現裡頭的寶藏~ 這裏放上 Github 官網,想查什麼案子直接打關鍵字就會出現相關資訊嘍!
/* 希望以上心得筆記和資訊有助於大家更了解 React 的運作~ 如果覺得獲益良多歡迎繼續關注我!
有任何問題都不吝指教(底下留言💬),大家一起學習、一起進步喲🗣
那~我們在其他系列見嘍!👋👋👋 */
參考資料 References:
- https://www.w3schools.com/react/react_lifecycle.asp
- https://zh-hant.reactjs.org/docs/hooks-effect.html
- https://www.cnblogs.com/marvintang1001/p/11867719.html
- https://www.zybuluo.com/qinyun/note/1401500