1. useRef trong cùng component
- Khi cả input và button đều trong một Component
- Khởi tạo inputRef bằng cách sử dụng hook
useRef
với giá trị ban đầu là null - Gán vào thẻ input thông qua thuộc tính
ref={inputRef}
- Khi click vào button thì set focus vào input
import { useRef } from 'react' export default function App() { const inputRef = useRef(null) const handleClick = () => { inputRef.current.focus() } return ( <> <input ref={inputRef} placeholder="Search..." /> <button onClick={handleClick}>Set focus</button> </> )
}
Demo: https://codesandbox.io/s/useref-simple-yc38mc
2. fowardRef từ component cha -> con
- Chuyển tiếp
fowardRef
từ component cha xuống component con - Tạo
inputRef
tại component cha - Component cha truyền
inputRef
cho component con như bên dưới
import { useRef } from 'react'
import MyInput from './components/MyInput' export default function App() { const inputRef = useRef(null) const handleClick = () => { inputRef.current.focus() } return ( <> <MyInput ref={inputRef} placeholder='Search...' /> <button onClick={handleClick}>Set Focus</button> </> )
}
- Tách input ra thành component con
MyInput
- Dùng
fowardRef
để nhận đầu vào các props vàref
là tham số thứ hai
import { forwardRef } from 'react' const MyInput = forwardRef((props, ref) => { const { placeholder, ...otherProps } = props return <input {...otherProps} ref={ref} placeholder={placeholder} />
}) export default MyInput
Demo: https://codesandbox.io/s/fowardref-p3c8mf
3. fowardRef toàn bộ
- Ở ví dụ 2 khi chúng ta tách input ra thành một component con
- Chúng ta đã public ra ngoài toàn bộ input này cho component cha
- Nên ở component cha có toàn quyền kiểm soát input này
- Điều này có thể gây ra những lỗi tiềm ẩn cho nội tại input đó
- Ví dụ như component cha xóa input đó thì có thể gây lỗi logic bên trong component con
- Ví dụ bên dưới component cha có thể xóa được luôn cả input đấy đi
import { useRef } from 'react'
import MyInput from './components/MyInput' export default function App() { const inputRef = useRef(null) const handleClick = () => { inputRef.current.remove() // DANGER } return ( <> <MyInput ref={inputRef} placeholder='Search...' /> <button onClick={handleClick}>Remove input</button> </> )
}
Demo: https://codesandbox.io/s/fowardref-2-wm5cq5
4. useImperativeHandle
- Để tránh việc public toàn bộ input ta sử dụng
useImperativeHandle
- Chúng ta sẽ chỉ public những gì có thể tương tác với input đó mà thôi
- Tại component con ta sử dụng
inputRef
nội tại của nó - Gán vào thẻ input thông qua thuộc tính
ref={inputRef}
- Sử dụng hook
useImperativeHandle
nhận ref từ component cha - Public method
setFocus
để component cha có thể sử dụng - Component cha chỉ có thể sử dụng method này để tương tác với component con
import { forwardRef, useRef, useImperativeHandle } from 'react' const MyInput = forwardRef((props, ref) => { const inputRef = useRef(null) useImperativeHandle( ref, () => ({ setFocus() { inputRef.current.focus() } }), [] ) const { placeholder, ...otherProps } = props return <input {...otherProps} ref={inputRef} placeholder={placeholder} />
}) export default MyInput
import { useRef } from 'react'
import MyInput from './components/MyInput' export default function App() { const myInputRef = useRef(null) const handleClick = () => { myInputRef.current.setFocus() } return ( <> <MyInput ref={myInputRef} placeholder='Search...' /> <button onClick={handleClick}>Set Focus</button> </> )
}