Khi làm việc với React, ta thường không thao tác trên DOM một cách trực tiếp. Tuy nhiên, sẽ có những trường hợp ta cần truy cập đến DOM chẳng hạn như khi ta muốn focus vào hay scroll đến một DOM node nào đó.
Getting a Ref to the Node
Trước tiên ta cần tạo ra một ref:
const inputRef = useRef(null)Liên kết ref với một JSX element thông qua thuộc tính ref để lấy ra DOM node của nó:
<input type="text" ref={inputRef}></input>Thuộc tính current của ref sẽ có giá trị là DOM node của element đang được liên kết:
console.log(inputRef.current) // <input type="text"></input>React sẽ cập nhật giá trị của ref trong quá trình commit (xem thêm Render and Commit). Thông thường, ta sẽ sử dụng ref ở trong các event handler hoặc effect.
Ví dụ minh họa:
import { useRef } from "react"
export default function Form() {
const inputRef = useRef(null)
function handleClick() {
inputRef.current.focus()
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>Focus the input</button>
</>
)
}Do đã được liên kết, ta có thể lấy ra giá trị của thẻ <input> thông qua thuộc tính value:
import { useRef } from "react"
function Form() {
const inputRef = useRef(null)
function handleClick() {
alert(inputRef.current.value)
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>Display the input</button>
</>
)
}Important
Hạn chế việc thêm, xóa hoặc sửa các DOM element được quản lý bởi React một cách thủ công.
Manage a List of Refs Using a Ref Callback
Giả sử ta có mảng các phần tử và một ref có tên là refList như sau:
import { useRef } from "react"
function List() {
const arr = [1, 2, 3]
const refList = useRef([])
return null
}Ta tạo ra một danh sách các phần tử từ mảng fruits:
import { useRef } from "react"
function Fruits() {
const fruits = ["🍎", "🍇", "🍋"]
const refList = useRef([])
return (
<ul>
{fruits.map((item, index) => (
<button key={index}>Show details of {item}</button>
))}
</ul>
)
}Để liên kết refList với các thẻ <button>, ta cần truyền vào thuộc tính ref của mỗi thẻ <button> một callback như sau:
function Fruits() {
const fruits = ["🍎", "🍇", "🍋"]
const refList = useRef([])
return (
<ul>
{fruits.map((item, index) => (
<button key={index} ref={(node) => (refList.current[index] = node)}>
Show details of {item}
</button>
))}
</ul>
)
}Ta gọi callback truyền vào là ref callback. Đối số của ref callback là một DOM node, bên trong callback ta gán từng phần tử của mảng các ref cho từng DOM node.
Accessing Another component’s DOM Nodes
Giả sử ta muốn truyền ref cho một component con nào đó, chẳng hạn như component Input như bên dưới:
import { useRef } from "react"
function Form() {
const inputRef = useRef(null)
return (
<form>
<Input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus the input</button>
</form>
)
}Thì ta cần bao bên ngoài component con (Input) bằng hàm forwardRef như sau:
import { forwardRef } from "react"
const Input = forwardRef((props, ref) => {
return <input type="text" ref={ref} />
})