← Về danh sách bài họcBài 8/25
📍 Bài 8: useRef - Tham Chiếu DOM & Giá Trị Persistent
🎯 Sau bài học này, bạn sẽ:
- Hiểu useRef và sự khác biệt với useState
- Truy cập DOM elements trực tiếp
- Lưu trữ giá trị persistent giữa các render
- Sử dụng forwardRef để truyền ref qua components
1. useRef Là Gì?
useRef tạo một object { current: value } tồn tại xuyên suốt lifecycle của component. Thay đổi .current KHÔNG gây re-render.
import { useRef, useState, useEffect } from 'react';
function RenderCounter() {
const [count, setCount] = useState(0);
const renderCount = useRef(0);
// Tăng mỗi render, nhưng KHÔNG gây re-render thêm
renderCount.current += 1;
return (
<div>
<p>Count: {count}</p>
<p>Render lần thứ: {renderCount.current}</p>
<button onClick={() => setCount(c => c + 1)}>+1</button>
</div>
);
}
2. Truy Cập DOM Elements
function SearchBox() {
const inputRef = useRef(null);
// Focus vào input khi mount
useEffect(() => {
inputRef.current.focus();
}, []);
const handleSubmit = () => {
alert(`Tìm: ${inputRef.current.value}`);
inputRef.current.value = '';
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} placeholder="Tìm kiếm..." />
<button onClick={handleSubmit}>🔍</button>
</div>
);
}
// Video player
function VideoPlayer({ src }) {
const videoRef = useRef(null);
return (
<div>
<video ref={videoRef} src={src} />
<button onClick={() => videoRef.current.play()}>▶️ Play</button>
<button onClick={() => videoRef.current.pause()}>⏸️ Pause</button>
</div>
);
}
3. Lưu Giá Trị Previous
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
// Sử dụng
function PriceTracker({ price }) {
const prevPrice = usePrevious(price);
return (
<div>
<p>Giá hiện tại: {price}đ</p>
<p>Giá trước: {prevPrice}đ</p>
<p>{price > prevPrice ? '📈 Tăng' : '📉 Giảm'}</p>
</div>
);
}
4. forwardRef
import { forwardRef, useRef } from 'react';
// Component con nhận ref từ cha
const FancyInput = forwardRef((props, ref) => (
<input
ref={ref}
className="fancy-input"
placeholder={props.placeholder}
/>
));
// Component cha
function Form() {
const inputRef = useRef(null);
return (
<div>
<FancyInput ref={inputRef} placeholder="Email" />
<button onClick={() => inputRef.current.focus()}>
Focus Input
</button>
</div>
);
}
📝 Tóm Tắt
useReftạo giá trị persistent, thay đổi không re-render- Truy cập DOM:
<input ref={myRef} />→myRef.current - Lưu previous value, render count, timer IDs
forwardReftruyền ref từ cha vào component con