React Hook Warnings для асинхронной функции в useEffect: функция useEffect должна возвращать функцию очистки или ничего - PullRequest
0 голосов
/ 16 ноября 2018

Я пытался использовать пример useEffect, как показано ниже:

useEffect(async () => {
    try {
        const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
        const json = await response.json();
        setPosts(json.data.children.map(it => it.data));
    } catch (e) {
        console.error(e);
    }
}, []);

, и я получаю это предупреждение в своей консоли.Но очистка необязательна для асинхронных вызовов, я думаю.Я не уверен, почему я получаю это предупреждение.Связывание песочницы для примеров.https://codesandbox.io/s/24rj871r0p enter image description here

Ответы [ 3 ]

0 голосов
/ 01 декабря 2018

Предлагаю посмотреть Дан Абрамов (один из создателей реакции) ответит здесь :

Я думаю, вы делаете это более сложным, чем нужно.

export default function Example() { 
    const [data, dataSet] = useState(false)

    async function fetchMyAPI() {
      let response = await fetch('api/data')
      response = await res.json()
      console.log(response);
      dataSet(response)
    }

    useEffect(() => {
      fetchMyAPI();
    }, []);

  return <div>{data}</div>
}

В долгосрочной перспективе мы будем препятствовать этой модели, потому что она стимулирует условия гонки.Например, между началом и окончанием вызова может произойти все, и вы могли бы получить новые реквизиты.Вместо этого мы рекомендуем Suspense для извлечения данных, который будет больше похож на

const response = MyAPIResource.read();

и никаких эффектов.Но в то же время вы можете переместить асинхронный материал в отдельную функцию и вызвать ее.

0 голосов
/ 11 февраля 2019

Пока React не предоставит лучший способ, вы можете создать помощника, useEffectAsync.js:

import { useEffect } from 'react';


export default function useEffectAsync(effect, inputs) {
    useEffect(() => {
        effect();
    }, inputs);
}

Теперь вы можете передать асинхронную функцию:

useEffectAsync(async () => {
    const items = await fetchSomeItems();
    console.log(items);
}, []);
0 голосов
/ 16 ноября 2018

Когда вы используете асинхронную функцию, такую ​​как

async () => {
    try {
        const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
        const json = await response.json();
        setPosts(json.data.children.map(it => it.data));
    } catch (e) {
        console.error(e);
    }
}

, она возвращает обещание, а useEffect не ожидает, что функция обратного вызова вернет Promise, скорее она ожидает, что ничего не возвращается или функция не возвращается.

В качестве обходного пути для предупреждения вы можете использовать самопризывающуюся асинхронную функцию.

useEffect(() => {
    (async function() {
        try {
            const response = await fetch(
                `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
        } catch (e) {
            console.error(e);
        }
    })();
}, []);

или, чтобы сделать ее более понятной, вы можете определить функцию и затем вызвать ее

useEffect(() => {
    async function fetchData() {
        try {
            const response = await fetch(
                `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
        } catch (e) {
            console.error(e);
        }
    };
    fetchData();
}, []);

второе решение облегчит чтение и поможет вам написать код для отмены предыдущих запросов, если новый был запущен, или сохранения последнего ответа на запрос в состоянии

Рабочие коды и коробка

...