Przejdź do głównej zawartości

05. Custom Hooks

Custom Hooks

Custom Hooks to funkcje JavaScript zaczynające się od use, które mogą wywoływać inne hooki. Pozwalają wyodrębnić powtarzającą się logikę komponentu (fetch, formularze, timery) do reużywalnych funkcji, bez zmiany struktury komponentów.

  1. Czym jest Custom Hook? — Funkcja useXxx enkapsulująca logikę z hookami React
  2. Jak różni się od utility function? — Może używać hooków React (useState, useEffect)
  3. Kiedy warto tworzyć Custom Hook? — Powtarzająca się logika w 2+ komponentach
  4. Zasady hooków — tylko na najwyższym poziomie, tylko w React functions
  1. Problem duplikacji logiki — ten sam fetch w trzech komponentach
  2. Tworzenie Custom Hooka — konwencja nazwy use, zwracanie wartości
  3. useFetch — pobieranie danych z loading/error states
  4. useLocalStorage — persystencja stanu w localStorage
  5. useDebounce — opóźnienie wywołania (wyszukiwarka)

Schemat

Przed: 3 komponenty z takim samym kodem fetch (30 linii każdy = 90 linii duplikacji). Po: 3 komponenty używające useFetch (3 linie każdy = 9 linii + 20 linii hooka = 29 linii). Oszczędność!

Przykład kodu JSX

Custom hook useFetch i dwa komponenty które go używają — pokazując eliminację duplikacji.

  • Co to jest Custom Hook i zasady tworzenia
  • useFetch — prosty przykład pobierania danych
  • Schemat: przed/po refaktorze

Forma: 10 slajdów, 10 minut

Ocena: 3.0
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(res => res.json())
.then(setData)
.catch(err => { if (err.name !== 'AbortError') setError(err.message); })
.finally(() => setLoading(false));
return () => controller.abort();
}, [url]);
return { data, loading, error };
}
// Użycie w komponencie — czyste i proste!
function UserList() {
const { data: users, loading, error } = useFetch('/api/users');
if (loading) return <p>Ładowanie...</p>;
if (error) return <p>Błąd: {error}</p>;
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}
function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initialValue;
});
const setStoredValue = (newValue) => {
setValue(newValue);
localStorage.setItem(key, JSON.stringify(newValue));
};
return [value, setStoredValue];
}
// Użycie: stan który przeżywa odświeżenie strony
function Settings() {
const [darkMode, setDarkMode] = useLocalStorage('darkMode', false);
return (
<button onClick={() => setDarkMode(!darkMode)}>
{darkMode ? 'Jasny motyw' : 'Ciemny motyw'}
</button>
);
}

Pokaż refaktor

Zacznijcie od komponentu z 40 liniami logiki fetch, potem pokażcie jak po wydzieleniu do Custom Hooka komponent ma 8 linii. Wow-efekt gwarantowany!

Zasada nazewnictwa

Podkreślcie że use na początku to nie konwencja dekoracyjna — React używa tej nazwy do weryfikacji reguł hooków. Hook bez use w nazwie nie będzie walidowany przez ESLint.

Custom Hooks = DRY w React!

Każdy senior React developer tworzy własne hooki. To znak dojrzałości kodu. Po tej prezentacji klasie zrozumie jak pisać czysty, reużywalny kod!