Ошибка при использовании пользовательского хука внутри useEffect - PullRequest
0 голосов
/ 02 апреля 2020
 let { photos, isQuering, empty, error } = useFetch(brand, isOld);

  useEffect(() => {
    if (isOld) {
      const { photos: photosTest } = useFetch(brand, isOld);
      photos = photosTest;
    }
  }, [isOld]);

useFetch - это пользовательский хук, который у меня есть, и я хочу вернуть старые фотографии, когда состояние isOld истинно, код выше useEffect вызывается нормально и фотографии загружаются, но я сталкиваюсь с ошибкой, что useFetch не вызываясь внутри тела компонента функции, появляется следующая ошибка «Недопустимый вызов ловушки. Хуки могут быть вызваны только внутри тела компонента функции. Это может произойти по одной из следующих причин:«, то есть я делаю что-то очень неправильное, чего я не вижу! Если бы вы могли мне помочь, я был бы очень признателен!

Редактирование из-за Данко! The Hook!

import { useEffect, useState, useContext } from 'react';
import { useScrollPagination } from './flow-manager';
import { db } from '../../Firebase';
import { userContext } from '../appContext';

export default function fetch(brand, isOld) {
  const {
    userData: { uid },
  } = useContext(userContext);

  const [photos, setPhotos] = useState([]);
  const [lastDoc, setLastDoc] = useState(undefined);
  const [isQuering, setIsQuering] = useState(false);
  const [empty, setEmpty] = useState(false);
  const [error, setError] = useState();
  const [finished, setFinished] = useState(false);
  const shouldFetchMore = useScrollPagination();
  const [shouldKeepFecthing, setShouldKeepFetching] = useState(false);

  useEffect(() => {
    if (isQuering || finished) return;
    if (!lastDoc || shouldFetchMore || shouldKeepFecthing) {
      setIsQuering(true);
      let query = !isOld
        ? db
            .collection('catalog-images')
            .where('brandName', '==', brand)
            .orderBy('timestamp', 'desc')
            .endBefore(new Date().setDate(new Date().getDate() - 40))
            .limit(20)
        : db
            .collection('catalog-images')
            .where('brandName', '==', brand)
            .where('photoPeriod', '==', 'Antiga')
            .limit(20);

      if (lastDoc) query = query.startAfter(lastDoc);

      query
        .get()
        .then(snap => {
          const newPhotos = [];
          let valid = 0;
          snap.forEach(doc => {
            const { url, pricetag, timestamp } = doc.data();
            if (!uid && pricetag === 'Sim') return;
            brand && newPhotos.push({ url, timestamp });
            valid += 1;
          });
          setPhotos(oldPhotos => [...oldPhotos, ...newPhotos]);
          setShouldKeepFetching(valid < 10);
          setEmpty(snap.empty);
          setLastDoc(snap.docs[snap.docs.length - 1]);
          setFinished(snap.docs.length < 20);
          setIsQuering(false);
        })
        .catch(setError);
    }
  }, [!!lastDoc, shouldFetchMore, shouldKeepFecthing, isQuering]);
  return { photos, isQuering, empty, error, fetch };
}

Последнее обновление: Здесь, где я вызываю ловушку:

let {
    photos,
    isQuering,
    empty,
    error,
    useFetch: refetch,
  } = useFetch(brand, isOld);

  useEffect(() => {
    if (isOld) {
      let { photos: photosTest } = refetch(brand, isOld);
      photos = photosTest;
      setIsOld(false);
    }
  }, [isOld]);

Ааа, ловушка:

import { useEffect, useState, useContext } from 'react';
import { useScrollPagination } from './flow-manager';
import { db } from '../../Firebase';
import { userContext } from '../appContext';

export default function useFetch(brand, isOld) {
  const {
    userData: { uid },
  } = useContext(userContext);

  const [photos, setPhotos] = useState([]);
  const [lastDoc, setLastDoc] = useState(undefined);
  const [isQuering, setIsQuering] = useState(false);
  const [empty, setEmpty] = useState(false);
  const [error, setError] = useState();
  const [finished, setFinished] = useState(false);
  const shouldFetchMore = useScrollPagination();
  const [shouldKeepFecthing, setShouldKeepFetching] = useState(false);

  useEffect(() => {
    if (isQuering || finished) return;
    if (!lastDoc || shouldFetchMore || shouldKeepFecthing) {
      setIsQuering(true);
      let query = !isOld
        ? db
            .collection('catalog-images')
            .where('brandName', '==', brand)
            .orderBy('timestamp', 'desc')
            .endBefore(new Date().setDate(new Date().getDate() - 40))
            .limit(20)
        : db
            .collection('catalog-images')
            .where('brandName', '==', brand)
            .where('photoPeriod', '==', 'Antiga')
            .limit(20);

      if (lastDoc) query = query.startAfter(lastDoc);

      query
        .get()
        .then(snap => {
          const newPhotos = [];
          let valid = 0;
          snap.forEach(doc => {
            const { url, pricetag, timestamp } = doc.data();
            if (!uid && pricetag === 'Sim') return;
            brand && newPhotos.push({ url, timestamp });
            valid += 1;
          });
          setPhotos(oldPhotos => [...oldPhotos, ...newPhotos]);
          setShouldKeepFetching(valid < 10);
          setEmpty(snap.empty);
          setLastDoc(snap.docs[snap.docs.length - 1]);
          setFinished(snap.docs.length < 20);
          setIsQuering(false);
        })
        .catch(setError);
    }
  }, [!!lastDoc, shouldFetchMore, shouldKeepFecthing, isQuering]);
  return { photos, isQuering, empty, error, useFetch };
}

Ответы [ 2 ]

2 голосов
/ 02 апреля 2020

Я бы предложил что-то еще:

  1. обновите ваш useFetch, чтобы он имел функцию refetch end и добавьте его к возвращаемому объекту.
  2. теперь, ваш обновленный хук может быть разобрано следующим образом: const { photos, isQuering, empty, error, refetch } = useFetch(brand);
  3. ваш useEfect можно использовать следующим образом:
  useEffect(() => {
    if(isOld) {
      refetch();
      setIsOld(false)
    }
  }, [isOld]);

Обновление:

Вы должны переименовать свой крючок custon в начать с use. В противном случае реакция не будет отличаться от других функций. Поэтому вместо названия fetch переименуйте его в useFetch.

0 голосов
/ 03 апреля 2020

Дело в том, что вы не можете вызвать хук из других хуков. Крючки вызываются только из тела компонента (верхнего уровня). Ваш код не имеет смысла на нескольких уровнях:

let { photos, isQuering, empty, error } = useFetch(brand, isOld);

useEffect(() => {
  if (isOld) {
    const { photos: photosTest } = useFetch(brand, isOld); // can't call a hook here
    photos = photosTest; // can't mutate component-level variables
  }
}, [isOld]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...