在useEffect中使用自定义钩子时出错

时间:2020-04-02 19:15:38

标签: javascript reactjs react-hooks

foo::foo

useFetch是我拥有的一个自定义钩子,我想在isOld状态为true时携带旧照片,正常调用useEffect上面的代码并加载照片,但是我遇到了一个错误,即未调用useFetch在函数组件的内部,出现以下错误“无效的钩子调用。只能在函数组件的主体内部调用钩子。这可能由于以下原因之一发生:”,也就是说,我正在做一些非常重要的事情。我看不到的错!如果您能帮助我,我将不胜感激!

由于Danko而进行编辑!钩子!

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

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

最新更新: 在这里,我在调用钩子:

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 };
}

Aaaand,这个钩子:

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

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

2 个答案:

答案 0 :(得分:3)

我建议别的东西

  1. 更新您的useFetch,使其具有refetch函数结束将其添加到返回的对象中。
  2. 现在,可以像这样const { photos, isQuering, empty, error, refetch } = useFetch(brand);
  3. 来破坏更新后的钩子
  4. 您的useEfect可以这样使用:
  useEffect(() => {
    if(isOld) {
      refetch();
      setIsOld(false)
    }
  }, [isOld]);

更新:

您必须重命名custon挂钩以use开头。否则,无法做出反应将其与其他功能区分开。因此,与其将其命名为fetch,而是将其重命名为useFetch

答案 1 :(得分:0)

问题是,您不能从另一个挂钩中调用一个挂钩。挂钩仅从组件主体(顶层)中调用。您的代码在几个层面上毫无意义:

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]);