React: Jak używać async i await w useEffect?

Opublikowano: 07.02.2023 - tagi: React JavaScript Komponent Hook useEffect Asynchroniczność

Asynchroniczny useEffect?

Obsługa żądań HTTP w useEffect jest prosta:

import { useState, useEffect } from 'react';

const Component = () => {
	const [state, setState] = useState(null);
	
	useEffect(() => {
		fetch('/api/data').then((data) => setState(data));
	}, []);
}

A co jeśli chcesz użyć async/await?

Może tak?:

import { useState, useEffect } from 'react';

const Component = () => {
    const [state, setState] = useState(null);

    useEffect(async () => {
        const data = await fetch('/api/data');
        setState({ data });
    }, []);
}

To zadziała, ale nie powinno się pisać w taki sposób. Dlaczego? useEffect umożliwia wywołanie funkcji, kiedy komponent nie jest już potrzebny. Dzięki niej możemy po sobie posprzątać, o ile jest taka potrzeba.

Załóżmy jednak, że potrzebujesz wywołać funkcję "czyszczącą":

import { useState, useEffect } from 'react';

const Component = () => {
    const [state, setState] = useState(null);

    useEffect(async () => {
        const data = await fetch('/api/data');
        setState({ data });

        return () => {
            ...
        }
    }, []);
}

Problem polega na tym, że z powodu użycia async/await w taki sposób funkcja "czyszcząca" nigdy nie zostanie wywołana!

Jak użyć async/await?

Rozwiązanie tego problem jest bardzo proste. Można to zapisać w taki sposób:

import { useState, useEffect } from 'react';

const Component = () => {
    const [state, setState] = useState(null);

    useEffect(() => {
        const fetchData = async () => {
            const data = await fetch('/api/data');
            setState({ data });
        }
        
        fetchData();
        
        return () => {
            ...
        }
    }, []);
}