###### tags: `react` # react ## Q1:有哪些生命週期的函數 ([lifeCycle](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)) 更完整的可以參考:https://www.fooish.com/reactjs/component-lifecycle.html#getDerivedStateFromProps 1. Mounting: 頁面被載入之前執行,通常只被執行一次,使用就是為了避免component被重複執行 -- componentwillMount() * 變成unsafe的惹 (1) constructor() * for初始化或綁定方法,如果都不需要的話就可以不用寫 * 在一開始須加上super(props) * 會在其他mount之前被呼叫 (2) static getDerivedStateFromProps() (3) render() ([參考](https://ithelp.ithome.com.tw/articles/10221975)) * 這個時期,有些元素並未真的渲染到DOM上面,如果需要跟瀏覽器有互動,需要配合componentDidMount() * 當每次props或是state被改變時,就會被執行一次 * 並不會改變component的state * 若shouldComponentUpdate()的回傳值為false的話,render()將不會被呼叫 (4) componentDidMount() * 操作「和render()中return的元素」有關的DOM * 在component被render到DOM之後才會執行 * 避免render中return無法操作 * 需要DOM node初始化的資料應該寫在這 * 適合寫subscription,設定完之後記得也在componentWillUnmount()內取消subscription 2. Updating: 更新 (1) shouldComponentUpdate() * 確認函數是否真的要被update * 會在新的prop或state被接收後、component被render之前被呼叫 * 預設為true * 不會在component初次render或使用forceUpdate()時被呼叫 * 存在的目的是效能最佳化 * React.PureComponent跟React.Component()的差異就在React.Component()沒有實作此方法,如果需要的化,可以使用PureComponent降低錯過必要更新的機會 * 可以將 this.props 和 nextProps 以及 this.state 和 nextState 做比較並回傳 false 以告知 React 這次的更新可以被略過。請注意,回傳 false 並不會避免 child component 在它們的 state 改變時重新 render (2) componentWillUpdate() * unsafe_ (3) componentDidlUpdate() * 更新之後會做的事情,在這裡才會真的將更新後的資料渲染到網頁上 (4) componentWillReceiveProps(nextProps, nextContext) * unsafe_ 3. Unmounting: 從頁面移除元素 (1) componentWillUnmount() * 當component被unmount或destroy後被呼掉 * 常搭配componentDidMount使用,移除在componentDidMount()裡的subscription * 因為放componentDidMount的內容就是怕重複執行,但裡面可能又有render,讓事件被呼叫等等,所以搭配此方法避免render渲染網頁 > constructor() > mount > update > unmount ## Q2:State 和 props的差別([參考](https://github.com/uberVU/react-guide/blob/master/props-vs-state.md) & [參考](https://ithelp.ithome.com.tw/articles/10185095) & [參考](https://https://ithelp.ithome.com.tw/articles/10210221)) ### State * 使用方式: 在component被管理(似function裏面的變數 * 不可以在parent component、child component裡面改變資料 * 可以改面裡面的component * 要改變state,必須使用setState() * 通常在component的 constructor 設定state初始值。 ### Props * 使用方式: 資料從外部傳進component (類似component參數 * 可以在parent component、child component裡面改變資料 * 資料由父層傳遞給子層 * 不能改裡面的component > 相同處 * 可以被parent component初始化 * 都會觸發render * 都是JS物件 * 可以有預設值 * 可以在child component裡面設定初始化的值 ## Q3:哪些地方不能setState ([參考](https://https://ithelp.ithome.com.tw/articles/10185194)& [參考](https://www.fooish.com/reactjs/component-lifecycle.html)) 1. constructor() > 要用this.state 2. render() > 不能setState > 會造成無窮迴圈 3. componentWillUpdate(nextProps, nextState) > 會導致state錯亂 4. componentWillUnmount() > 因為這個 component 永遠不會再重新 render 5. getDerivedStateFromProps() > 在componnent被render前被呼叫 > 從props取得state * componentWillMount() < unsafe_ > ### 需要寫this.setState() > * componentDidMount > -- 這裡setState()會觸發額外的render,但是user不會看到 :D 不過會產生效能問題 > * componentDidUpdate() > -- 會在更新之後馬上被呼叫,但是初次render不會呼叫到此方法 > -- 在component更新之後,可以在此對DOM進行運作 > -- 必須配合if條件判斷,以免更新之後會造成無限迴圈或是過度消耗效能 > -- 如果shouldComponentUpdate()回傳false的話,componentDidUpdate()就不會被呼叫 > * 使用時機 setState 函數會依序更新的 state 物件,然後告訴 React 應該要重新 render 這個 component 以及他的子 component。這個函數可運用在事件觸發以及對 server 請求後資料變動帶來的畫面更新。 > https://zh-hant.reactjs.org/docs/state-and-lifecycle.html > V.S不能使用status 1. 沒有繼承component的時候(也就是作為function component的時候) ## Q4: Class component VS function component([參考](https://ithelp.ithome.com.tw/articles/10234746)) | | Class component | function component | | -------- | -------- | -------- | | 繼承component | Y | N | | 使用status | Y | N | | 需要實作render() | Y | N | | 擁有、使用this | Y | N | | 生命週期 | Y | N | | props | 每次拿到最新的(因為使用this,this一直在變化) | 一直是原本傳進來的那個 | | 部分prop及state更改 | 整個component重新被載入 | 可以利用useEffect改變幾個value就好(比較省效能) | > 不需要紀錄state,且只需要render畫面的時候,就很適合使用function component ## JS筆記 ### About JS SE6 1. 箭頭函數(上下相等) 大致寫法 ```javascript=1 var fn = function(){ console.log(this); } var fn = () =>{ console.log(this); } ``` 詳細解說:https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions 2. Const 有點像使用`let`所宣告的變數,不可以被重複指定或重複宣告,且具有區域性。(https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Statements/const) ## React * 建立react的最小單位是element。 * 與瀏覽器的 DOM element 不同,React element 是單純的 object,而且很容易被建立。React DOM 負責更新 DOM 來符合 React element。 * props是properties的簡稱。 * 我們遵循的傳統通常是用 on[Event] 來命名那些代表 event 的 prop,用 handle[Event] 來命名那些 handle event 的方法 * React 會自動使用 key 來決定哪一個 component 需要被更新。一個 component 無法得知自身的 key 是什麼 ### component簡介 * react有數種不同的component來建構複雜的UI,而component是由element所組成的。 * component小巧且獨立。 * component一定要繼承react.component。 * component裡面可以包含其他component。 * component VS purecomponent * purecomponent實作了shouldComponentUpdate方法,for比較不常render的component * shouldComponentUpdate的方法只是檢查props.color或state.count是否有任何變化。如果這些值不變,則組件不會更新 * PureComponent會利用shallow-compare的方式進行比較,shallow compare簡單來說就是對於基本型態(number、string...)是嚴格比較而對於物件則是比較是否指向同一個記憶體空間` ### component分類 1. React.component 2. function component * 裡面沒有`state`的component ### Render簡介 * 當資料改變時,React會透過render更新component。 * render會回傳一個React element,通常使用特殊語法,稱為JSX。這種寫法讓結構寫起來更容易 ### Render用法(component) 在最後的地方會呼叫App,App會從line12執行,遇到line16執行line7,又遇到line17去執行line2醬([參考](https://hugh-program-learning-diary-js.medium.com/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6-react-react-%E5%9F%BA%E7%A4%8E-39af71f84886)) ```javascript=1 import React, { Component } from 'react'; class Text extends Component { // 新增 render() { return <p>text</p> } } class Title extends Component { render() { return <h1>title</h1> } } class App extends Component { render() { return ( <div> <Title /> <Text /> // 這樣子引用 </div> ) } } export default App ``` ### JSX寫法 * 其實就是js+HTML混合體,like `return <h1>Titel</h1>` 特別寫法([參考](https://https://hugh-program-learning-diary-js.medium.com/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6-react-react-%E5%9F%BA%E7%A4%8E-39af71f84886)): 1. 標籤裡面的 `class` 要寫成 `classname` 2. js的部分要用 `{}` (裡面可以放加號),這用法類似於 `${}`,如果是以這個方式寫style,那css的命名需用小駝峰式命名法 ```javascript=1 <div class="title" style={JS語法}> </div> ``` 3. css的部分要用`{{}}` ```javascript=1 <div class="title" style={{CSS物件}}> </div> ``` 4. return的內容如果要換行寫,記得寫 `()` ```javascript=1 return <div> <h1>Title</h1> </div> return ( <div> <h1>Title</h1> </div>) ``` 5. 可以直接在標籤內加上click函式 ```javascript= <h1 onClick={() => { alert('hi'); }}> hello </h1> ``` **注意:JSX 的 onClick 是大寫,html 的則是小寫 onclick** 6. 要使用state需要加上 (1) ```javascript=1 constructor(){ super(); //因為有繼承所以要用這個語法 this.state = { counter:1; } } ``` (2) ```javascript=1 <h1 onClick={this.handleClick.bind(this)}>{this.state.title}</h1> ``` (3) ```javascript=1 <counter number={this.state.counter}/> class Counter extends Component { render() { return ( <div>{this.props.number}</div> // 利用 .props 指向那個設定值 ) } } ``` (4) ```javascript=1 import React, { Component } from 'react'; class Counter extends Component { render() { return ( <div>{this.props.number}</div> ) } } class App extends Component { constructor() { super() // 因為有繼承要用這個語法 this.state = { title: 'hello', counter: 1, } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState({ counter: this.state.counter + 1 }) } render() { return ( <div> <h1 onClick={this.handleClick}>{this.state.title}</h1> <Counter number={this.state.counter}/> </div> ) } } export default App ``` (5)(不建議,屬實驗性的功能,需另外加裝plugin才可以使用) ```javascript=1 handleClick = () => { this.setState({ counter: this.state.counter + 1 }) } ``` ### 補充方法 1. getSnapshotBeforeUpdate() * 在最近一次render的output給DOM時被呼叫,可以在DOM改變之前先獲取其中的資訊,回傳值會當參數傳給componentDidUpdate() 2. static getDerivedStateF romError(error) * 在descendant component拋出錯誤後被呼叫 * 會接收錯誤並回傳參數以更新state 3. componentDidCatch(error,info) * 在descendant component拋出錯誤後被呼叫 * 接收兩個參數 * error - 被拋出的參數 * info - 包含componentStack的object,內含錯誤訊息 ### function寫法 1. ```javascript=1 function Counter(props) { return ( <div>{props.number}</div> ) } class App: <Counter number={this.state.counter} /> ``` 2. ```javascript=1 function Counter(props) { const {number} = props; return ( <div>{number}</div> ) } ``` 3. ```javascript=1 function Counter({number}) { //{number}等同於 props.number return ( <div>{number}</div> ) } ``` 4. ```javascript=1 const Counter = ({number}) => { return ( <div>{number}</div> ) } ``` ### constructor()介紹 * 做為資料的宣告、初始化、預備、函式綁定等等 * 通常只有兩個用途: 1. 透過this.state初始化state `Constructor 是唯一一個你應該直接指定 this.state 的地方。在所有其他的方法中,你則需要使用 this.setState()。 ` 2. 為event handler方法綁定instance * 如果沒有初始化state也不綁定方法的話,就不需要constructor * subclass建立constructor時,應該先呼叫super(props),不然會出現undefined * 不能呼叫setState() ### Hook * hook是function * 在class裡面無法使用 * 需要在程式最頂端寫 `import React, {useState(等有用到的hook)} from 'react';` * 只能在function的最外層(最上層) * 只能在react function呼叫hook(JS function沒有hook) * 可以在hook呼叫hook * 可以在function component呼叫hook * 可以自定義hook,以避免寫重複的code、也可以共享邏輯 :) > 1 . useState: > * 在function裡面可以使用state > 2. useEffect: > * 可以視為componentDidMount+componentDidUpdate +componentWillUnmount。 > * 表示在render之後做甚麼事情,也可以直接從effect存取state變數或props。 > * 執行時機是在每次render之後,而不考慮mount和update > 3. [其他](https://zh-hant.reactjs.org/docs/hooks-reference.html) history 放在最外層???? 原本只有要顯示現在玩遊戲的狀態,之後要加上button可以回到過去 因為button會在GAME裡面,所以把history也移到button裡面 (why 適合嗎 怎麼改) 好像不太適合 因為覺得GAME裡面有點太多東西 希望怎麼改 可以在function Game的return裡面加一個function component,這個component專門生出可以回到歷史紀錄的button history可以放在board value可以借由props傳出來(參考步數) 如果要放history應該要放game,因為board只有管畫面 當按下click之後,Square{button onClick={props.onClick}} >> Board return (<Square onClick={() => props.onClick()}></Square>}>) >> Game return (<Board onClick()={(i:number) => handleClick(i)}>) handleClick(i)會setState,所以會使return重新render render會使Board跟Square裡面,props有改變的地方更新
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up