---
# System prepended metadata

title: react
tags: [react]

---

###### 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有改變的地方更新