Chào mọi người lại là Slao đây,
Sau đây sẽ là top 5 Custom Hook thuận tiện và mới lạ để mọi người có thể sử dụng
useMediaQuery
useMediaQuery lắng nghe các truy vấn media, cho phép bạn áp dụng các kiểu hoặc hành vi cụ thể dựa trên kích thước thiết bị
import { useEffect, useState } from 'react';
function useMediaQuery(query) {
const [matches, setMatches] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia(query);
setMatches(mediaQuery.matches);
const handler = event => setMatches(event.matches);
mediaQuery.addEventListener('change', handler);
return () => mediaQuery.removeEventListener('change', handler);
}, [query]);
return matches;
}
Cách dùng
const isLargeScreen = useMediaQuery('(min-width: 1024px)');
useWebSocket
useWebSocket hook kết nối ứng dụng của bạn với WebSocket server, dễ dàng gửi và nhận real-time dữ liệu. Nó xử lí các kết nối lại, message buffering, và event-base handling, làm cho dễ dàng cập nhập thời gian thực
Ví dụ này trình bày một hook WebSocket có thể tái sử dụng với các tính năng quản lý kết nối, xử lý sự kiện và dọn dẹp gọn gàng.
import { useState, useEffect, useRef, useCallback } from 'react';
function useWebSocket(url, options = {}) {
const { reconnect = true, reconnectInterval = 5000, onOpen, onMessage, onError, onClose } = options;
const [isConnected, setIsConnected] = useState(false);
const [lastMessage, setLastMessage] = useState(null);
const websocketRef = useRef(null);
const reconnectTimeout = useRef(null);
const connect = useCallback(() => {
websocketRef.current = new WebSocket(url);
websocketRef.current.onopen = (event) => {
setIsConnected(true);
onOpen && onOpen(event);
};
websocketRef.current.onmessage = (event) => {
setLastMessage(event.data);
onMessage && onMessage(event);
};
websocketRef.current.onerror = (event) => {
onError && onError(event);
};
websocketRef.current.onclose = (event) => {
setIsConnected(false);
onClose && onClose(event);
if (reconnect) {
reconnectTimeout.current = setTimeout(connect, reconnectInterval);
}
};
}, [url, reconnect, reconnectInterval, onOpen, onMessage, onError, onClose]);
const sendMessage = useCallback((message) => {
if (isConnected && websocketRef.current) {
websocketRef.current.send(message);
}
}, [isConnected]);
useEffect(() => {
connect();
return () => {
if (websocketRef.current) {
websocketRef.current.close();
}
clearTimeout(reconnectTimeout.current);
};
}, [connect]);
return { isConnected, sendMessage, lastMessage };
}
Các tính năng của useWebSocket
- Reconnection Handling: nếu kết nối đóng, nó sẽ tự động kết nối lại sau 1 khoảng thời gian nhất định
- Event Handling: chấp nhận các thuộc tính gọi lại onOpen, onMessage, onError, and onClose events để xử lí khi cần thiết
- Message Sending: cung cấp chúc năng sendMessage cái mà chỉ gửi message khi websocket mở
- Last Message Storage: lưu dữ liệu mới nhất nhận được , chấp nhận các dữ liệu gần nhất mà không cần đăng kí.
Cách dùng
function ChatApp() {
const { isConnected, sendMessage, lastMessage } = useWebSocket('ws://localhost:4000/chat', {
reconnect: true,
reconnectInterval: 3000,
onOpen: () => console.log('Connected to WebSocket'),
onMessage: (event) => console.log('New message received:', event.data),
onClose: () => console.log('Disconnected from WebSocket'),
});
const [inputValue, setInputValue] = useState('');
const handleSend = () => {
sendMessage(inputValue);
setInputValue('');
};
return (
<div>
<h3>WebSocket Chat</h3>
<div>
<p>{isConnected ? 'Connected' : 'Disconnected'}</p>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Type your message..."
/>
<button onClick={handleSend} disabled={!isConnected}>
Send
</button>
</div>
<div>
<h4>Last Message:</h4>
<p>{lastMessage}</p>
</div>
</div>
);
}
useHover
Phát hiện di chuột qua 1 phần tử để xử lí cho các công cụ, hình ảnh động hoặc bất kì phản hồi UI nào trên trạng thái di chuột
import { useState, useRef, useEffect } from 'react';
function useHover() {
const [hovered, setHovered] = useState(false);
const ref = useRef(null);
useEffect(() => {
const handleMouseOver = () => setHovered(true);
const handleMouseOut = () => setHovered(false);
const node = ref.current;
if (node) {
node.addEventListener('mouseover', handleMouseOver);
node.addEventListener('mouseout', handleMouseOut);
}
return () => {
if (node) {
node.removeEventListener('mouseover', handleMouseOver);
node.removeEventListener('mouseout', handleMouseOut);
}
};
}, [ref]);
return [ref, hovered];
}
const [hoverRef, isHovered] = useHover();
useDebounce
Ngăn chặn sự kích hoạt nhanh chóng của các sự kiện, đã sử dụng có thể hữu ích cho các trường đầu vào hoặc thanh tìm kiếm
import { useState, useEffect } from 'react';
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => clearTimeout(handler);
}, [value, delay]);
return debouncedValue;
}
const debouncedSearchTerm = useDebounce(searchTerm, 500);
useInfiniteScroll
useInfiniteScroll hook rất hữu ích để tìm nạp dữ liệu khi người dùng scroll xuống. Nó có thể xử líu các state phúc tạp như loading, error handling, pagination...
import { useState, useEffect, useRef, useCallback } from 'react';
function useInfiniteScroll(fetchData, options = {}) {
const { threshold = 0.8, hasMore = true } = options;
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const observerRef = useRef();
const loadMore = useCallback(async () => {
if (loading || !hasMore) return;
setLoading(true);
setError(null);
try {
const newData = await fetchData();
setData((prevData) => [...prevData, ...newData]);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
}, [fetchData, loading, hasMore]);
useEffect(() => {
if (!hasMore) return;
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadMore();
}
},
{ threshold }
);
if (observerRef.current) observer.observe(observerRef.current);
return () => {
if (observerRef.current) observer.unobserve(observerRef.current);
};
}, [loadMore, hasMore, threshold]);
return { data, loading, error, observerRef };
}
function InfiniteScrollList() {
const fetchMoreData = async () => {
const response = await fetch('/api/data'); // Example API
return response.json();
};
const { data, loading, error, observerRef } = useInfiniteScroll(fetchMoreData, {
threshold: 0.9,
hasMore: true
});
return (
<div>
{data.map((item, index) => (
<div key={index}>{item}</div>
))}
<div ref={observerRef} style={{ height: '1px' }} />
{loading && <p>Loading...</p>}
{error && <p>Error loading data...</p>}
</div>
);
}
Top comments (0)