---
# System prepended metadata

title: About Ref in React

---

# About Ref in React
### 1. 開頭
refs和state十分相似，兩者都能建立變數，並且對其進行讀跟寫
```
const [num, setNum] = useState(0)
const number = useRef(0)
```
useState必須使用特定的設定涵式來進行state的設定，而useRef(initialValue)則是會return一個 **{ current: initialValue }的物件** ，可以使用.current的方式直接進行讀跟寫。

例:
```
number.current = 1

console.log(number.current) // 1
```


### 2. 相異處
#### 而兩者最大的不同點在於state改變的時候會觸發re-render，反之refs並不會觸發re-render

因此就會發生以下的情況:

```
1. 在按下button後，button上的數字會隨著按的次數增加

const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You clicked {count} times
    </button>
  );
```

```
2. 在按下button後，由於不會re-render因此button上的數字不會隨著按的次數增加

let countRef = useRef(0);

  function handleClick() {
    // This doesn't re-render the component!
    countRef.current = countRef.current + 1;
  }

  return (
    <button onClick={handleClick}>
      You clicked {countRef.current} times
    </button>
  );
```

並且若state改變了值，新的值必須在進行re-render過後才能夠被取得(**re-render的觸發時機是在function完整執行完後才會觸發**)。

而refs則是會**立刻改變**而且能立刻讀到更新過後的值。

然而雖然兩者看起來有點相似，但在基本上都會以使用useState為主，因為refs是一種 “escape hatch” 在通常情況下並不會頻繁的做使用。

### 3. 對比


|                   refs                    |                    state                     |
|:-----------------------------------------:|:--------------------------------------------:|
| useRef(value) 會 return { currnet: value } |useState(value)會return一個[state, setState] |
|       當值被更新時**不會**觸發re-render       |        當值被更新時**會**觸發re-render    |
|current的值本身能夠進行更改跟讀取|值不能進行更改，必須使用提供的設定涵式才能對值進行更改，並且新的值要在re-render後才能得到|
|不要在render時對refs進行讀或寫，容易讓程式變得難以預測|可在任何時候進行讀跟寫|

### 4. refs使用時機

通常refs會使用在不需要render的東西，或者是DOM的element上

1. 像是如果我們想知道畫面re-render的次數，如果這時假如使用state進行計數的話
```
const [renderTimes, setRenderTimes] = useState(0)

useEffect(()=>{
    setRenderTimes(prev=>prev+1)
})

// 由於state改變造成re-render，而re-render又觸發useEffect，因此形成無限迴圈
```

但如果改成用refs實作的話就能進行計算
```
import React, { useState, useEffect, useRef } from 'react';

export default function Counter() {
  const [text, setText] = useState('')
  const renderTimes = useRef(1)

useEffect(()=>{
    renderTimes.current = renderTimes.current + 1
    console.log('render')
})

return (
    <>
        <input value={text} onChange={data=>setText(data.target.value)}/>
        <div>text = {text}</div>
        <div>renderTimes = {renderTimes.current}</div>
    </>
)
}
```

2. 使用在DOM的element上的話
```
實現按button後focus到input上

const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        Focus the input
      </button>
    </>
  );
```



---
參考資料:
https://react.dev/learn/referencing-values-with-refs
https://react.dev/learn/manipulating-the-dom-with-refs
https://www.youtube.com/watch?v=42BkpGe8oxg
https://www.youtube.com/watch?v=t2ypzz6gJm0