Custom Hooks - بناء Hooks مخصصة — مقدمة React
Custom Hooks
Custom Hooks تسمح لك باستخراج منطق المكون لإعادة استخدامه.
قواعد Custom Hooks
1. اسم الـ Hook يجب أن يبدأ بـ "use"
2. يمكنها استدعاء hooks أخرى
3. يجب استدعاؤها في مستوى أعلى (ليس داخل شروط أو loops)
مثال: useLocalStorage
function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch {
return initialValue;
}
});
const setStoredValue = (newValue) => {
setValue(newValue);
localStorage.setItem(key, JSON.stringify(newValue));
};
return [value, setStoredValue];
}
// الاستخدام
function Settings() {
const [theme, setTheme] = useLocalStorage('theme', 'light');
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
الوضع: {theme}
</button>
);
}مثال: useFetch
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
setLoading(true);
fetch(url, { signal: controller.signal })
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(err => {
if (err.name !== 'AbortError') {
setError(err.message);
setLoading(false);
}
});
return () => controller.abort();
}, [url]);
return { data, loading, error };
}
// الاستخدام
function UsersList() {
const { data: users, loading, error } = useFetch('/api/users');
if (loading) return <p>جارٍ التحميل...</p>;
if (error) return <p>خطأ: {error}</p>;
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}// useWindowSize - Hook لحجم النافذة
function useWindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight
});
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return size;
}
// useToggle - Hook بسيط للتبديل
function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
const toggle = () => setValue(v => !v);
return [value, toggle];
}
// الاستخدام
function Modal() {
const [isOpen, toggleModal] = useToggle(false);
const { width } = useWindowSize();
return (
<>
<button onClick={toggleModal}>
{isOpen ? 'إغلاق' : 'فتح'} Modal
</button>
{isOpen && (
<div className={width < 768 ? 'modal-mobile' : 'modal-desktop'}>
محتوى Modal
</div>
)}
</>
);
}اختبر فهمك