繁体   English   中英

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

[英]Error using custom hook inside a useEffect

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

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

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

因为丹科而编辑! 钩子!

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

Aaaand,钩子:

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

我建议别的:

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

更新:

您必须重命名您的 custon hook 以开始use 否则,react 无法将其与其他功能区分开来。 因此,与其将其命名为fetchuseFetch将其重命名为useFetch

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM