iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
自我挑戰組

程式碼 AI 寫,我負責看懂:30 天拆解 React × TypeScript系列 第 10

Day 10|ref() 變成 useState()?兩個真的可以直接畫等號嗎?

  • 分享至 

  • xImage
  •  

從 Vue 的 ref() 開始看

在 Vue 中,會使用 ref() 記錄可能改變的資料。
例如 TodoForm.vue 使用 ref() 記錄輸入框目前的文字:

<script setup>
import { ref } from 'vue'

const text = ref('')
</script>

這裡傳入的空字串:

ref('')

text 一開始的值。

<script> 中取得或修改這個值時,需要使用 .value

console.log(text.value)

text.value = '學習 React'

送出表單後,專案也是透過 .value 清空內容:

text.value = ''

看到 React 專案時,原本的 ref() 不見了,改成了:

const [text, setText] = useState('')

第一眼很容易直接把它們想成:

Vue 的 ref() = React 的 useState()

但它們真的可以直接畫上等號嗎?

React 的 useState() 是什麼?

useState() 是 React 提供的 Hook,可以讓 Component 記住一個 State。
目前 TodoForm.tsx 中使用它記錄輸入框的文字:

import { useState } from 'react'

function TodoForm({ onAdd }: TodoFormProps) {
  const [text, setText] = useState('')

  // ...
}

和 Vue 的 ref('') 一樣,傳入的空字串是初始值:

useState('')

不同的是,useState() 會回傳一個包含兩個值的陣列:

const [text, setText] = useState('')

這兩個值分別是:

  • text:目前的 State
  • setText:更新 State 的函式

可以先理解成:

目前的值   更新值的函式
   ↓            ↓
[text,      setText]

React 官方文件中常見的基本寫法也是:

const [state, setState] = useState(initialState)

React 官方文件:useState

為什麼外面要使用中括號?

useState() 回傳的是一個陣列,因此這裡使用了 JavaScript 的陣列解構:

const [text, setText] = useState('')

如果不使用解構,可以先想成:

const result = useState('')

const text = result[0]
const setText = result[1]

使用陣列解構後,就可以直接把兩個值取出:

const [text, setText] = useState('')

textsetText 並不是 React 規定的固定名稱,但通常會按照這種方式命名:

const [something, setSomething] = useState(initialValue)

例如:

const [name, setName] = useState('')
const [count, setCount] = useState(0)
const [completed, setCompleted] = useState(false)

目前專案則使用:

const [text, setText] = useState('')

從名稱就能看出 text 是目前的文字,而 setText 負責更新文字。

React 要怎麼讀取 State?

Vue 在 JavaScript 中讀取 ref() 的值時,需要使用:

text.value

React 則可以直接使用 text

console.log(text)

在 JSX 中也可以直接將它放進輸入框:

<input
  type="text"
  value={text}
  placeholder="輸入待辦事項..."
/>

所以兩者讀取資料的方式不同:

// Vue
text.value
// React
text

React 要怎麼更新 State?

Vue 可以透過 .value 直接指定新的值:

text.value = ''

React 則要呼叫 useState() 提供的更新函式:

setText('')

目前 TodoForm.tsx 在送出表單後,就是這樣清空輸入框:

onAdd(trimmed)
setText('')

輸入內容發生變化時,也會使用 setText() 更新:

onChange={(event) => setText(event.target.value)}

setText() 收到新的文字後,React 會保存新的 State,重新 Render Component,並更新畫面。
因此 React 不是這樣更新:

text = ''

而是這樣:

setText('')

可以這樣理解:

text 負責提供目前的值,setText() 負責通知 React 更新這個值。

專案裡不只一個 useState()

除了輸入框的文字,App.tsx 也使用 useState() 記錄所有待辦事項:

const [todos, setTodos] = useState<Todo[]>([])

這裡的初始值是空陣列:

[]

而兩個解構出來的值分別是:

  • todos:目前的待辦事項陣列
  • setTodos:更新待辦事項陣列的函式

新增待辦事項時,專案會呼叫:

setTodos([...todos, newTodo])

刪除待辦事項時則會呼叫:

setTodos(todos.filter((todo) => todo.id !== id))

雖然傳入的新資料不同,但概念和 setText('') 一樣,都是透過 useState() 提供的函式更新 State。

偷偷說,useState<Todo[]>([]) 這段看起來很難懂、很混亂對叭但沒關係不用緊張因為我也還在熟悉中
<Todo[]> 是 TypeScript 的型別寫法,等後面進到 TypeScript 的部分時再仔細看。這裡先將重點放在 useState() 的用途,就不深入說明。

ref()useState() 真的一樣嗎?

這邊一樣將兩個專案的寫法放在一起比較:

// Vue
const text = ref('')
// React
const [text, setText] = useState('')

兩者的用途確實很接近:

  • 都可以保存 Component 需要記住的資料
  • 資料改變後都能讓畫面跟著更新
  • 都可以提供一個初始值

但實際使用方式並不相同:

Vue ref() React useState()
回傳一個 Ref 物件 回傳一個包含兩個值的陣列
在 JavaScript 中使用 .value 讀取 直接使用 State 變數讀取
使用 .value = 新值 更新 使用 setState(新值) 更新
例如 text.value = '' 例如 setText('')

如果只看「記錄會改變的資料」這個用途,ref()useState() 的確很像。
但它們不是完全相同的 API,也不能直接把 Vue 的寫法原封不動地搬到 React。

今日回顧

  • useState() 是 React 提供的 Hook,讓 Component 記住一個 State
  • useState(initialValue) 會回傳一個陣列,通常用 [something, setSomething] 解構出目前的值與更新函式
  • 讀取 State 時可以直接使用變數本身,不像 Vue 需要 .value
  • 更新 State 必須呼叫 setState() 函式,呼叫後 React 會重新 Render Component

一開始會覺得:

ref() 換成 useState() 就好了吧?

實際比較後才發現,兩者雖然都能記錄會改變的資料,但使用方式還是有明顯差異。Vue 把值放在 .value 裡,而 React 則把目前的值和更新它的函式一起交給我。這個中括號看久之後,好像也慢慢沒有一開始那麼陌生了。
那麼,下篇見!


上一篇
Day 09|v-if 去哪了?React 的條件渲染原來就是 JavaScript
下一篇
Day 11|為什麼 React 不讓我直接改資料?認識 State 更新
系列文
程式碼 AI 寫,我負責看懂:30 天拆解 React × TypeScript22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言