React Refs

在 React 中,可以透過 useState 在 component 重新選染時保留資料,並透過 handler & value 來為 JSX 與 JS 做到雙向綁定,但在某些情況下,會只有特定的時機會需要取得資料,並不需要隨時對資料進行監聽,因此 React 提供了一個更輕便的方式 - Refs 來達到這個目的

回到先前的範例,為了避免 component rendered 所造成的資料流失,我們會透過 state 來儲存在資料,並透過 handler 監聽資料的更動以即時更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const NewUser = props => {
const [user, setUser] = useState({
username: "",
age: "",
});

const submitHandler = (event) => {};

const usernameChangeHandler = () => {};

const ageChangeHandler = () => {};

return (
...
<form onSubmit={submitHandler}>
<label htmlFor="username">Username</label>
<input
id="username"
type="text"
value={user.username}
onChange={usernameChangeHandler}
/>
<label htmlFor="age">Age(Years)</label>
<input
id="age"
type="number"
value={user.age}
onChange={ageChangeHandler}
/>
<Button type="submit">Add User</Button>
</form>
);
};

React Refs

但其實我們不需要隨時監聽資料的更動,只需要在送出表單時,取得當前資料即可,因此 React 便提供了另一個 hooks - Refs ; 如同其他的 React hooks,Refs 也只能應用於 component function 之中,透過查看 useRefs 所傳的值,它總是會包含一個屬性 - current,這個屬性即是我們綁定的 DOM,其中的 value 即是 DOM value。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import {useRef} from 'react';

const NewUser = props => {
const nameInputRef = useRef();

const submitHandler = event => {
console.log(nameInputRef);
};

const usernameChangeHandler = (event) => {...};

return (
<form onSubmit={submitHandler}>
<label htmlFor="username">Username</label>
<input
id="username"
type="text"
value={user.username}
onChange={usernameChangeHandler}
ref={nameInputRef}
/>
...
</form>
);
};

透過 Refs,便可在送出表單時取得即時資料,因此先前綁定 State 所使用的監聽方式也不在必要,單純透過綁定 Refs 也可以直接更改 current.value 的值,如送出表單後清空欄位的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const submitHandler = (event) => {
...
nameInputRef.current.value = '';
ageInputRef.current.value = '';
};

return (
<form onSubmit={submitHandler}>
<label htmlFor="username">Username</label>
<input
id="username"
type="text"
ref={nameInputRef}
/>
...
</form>
);

Controlled vs Uncontrolled Components

在 React 中,透過 State 綁定資料與 JSX,及時監聽 JSX 變化,並透過 React 回填最新的資料,這種完全由 React 所主導的元件稱之為 - Controlled Component。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {useState} from 'react';

const component = () => {
const [username, setUsername] = useState();

const submitHandler = event => {
event.preventDefault();

...

setUsername('');
};

const usernameHandler = event => {
setUsername(event.target.value);
};

return (
<form onSubmit={submitHandler}>
<input value={username} onChnage={usernameHandler}/>
</form>
);
};

反之,透過 Refs 綁定 JSX 後,只在需要時即時查看最新資料,這種非完全透過 React 完全掌握資料變動的方式就稱為 - Uncontrolled component ; 但這裡也許會有些疑問是,在送出表單後,不也是透過更動 useRef 所回傳的 object.current.value 來達到主動更新資料嗎 ?

這裡的差異是,Ref 更新資料只是透過 DOM API 來更新 value,來不是完全由 React 提供的方式來辦到 ; 也許到目前為止還無法感受這麼區分的目的,但這在 React 的開發中是非常典型用來區分 component 開發模式的方式,在更進階的開發中會進一步探討它們的差異。

資料參考

React - The Complete Guide (Incl Hooks, React Router, Redux)