You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在每次渲染时传入不同查询调用自定义Hook useFetch?

解决方案

问题的核心是:当currPage更新时,虽然你生成了新的Firestore查询对象,但useFetch自定义Hook没有检测到这个查询的变化,因此没有重新触发数据获取。下面是具体的修复步骤:

1. 修复useFetch的依赖监听

如果useFetch是你自己实现的自定义Hook,确保它内部的useEffect将传入的查询对象作为依赖项。这样当查询对象变化时,会自动重新执行数据请求。

示例实现:

import { useState, useEffect } from 'react';
import { getDocs, onSnapshot } from 'firebase/firestore';

function useFetch(query) {
  const [data, setData] = useState(null);
  const [mats, setMats] = useState(null); // 根据你的业务逻辑保留或调整

  useEffect(() => {
    // 处理实时监听的取消逻辑(如果用了onSnapshot)
    let unsubscribe = null;

    const fetchData = async () => {
      if (!query) return;

      // 方式1:一次性获取数据
      const snapshot = await getDocs(query);
      const result = snapshot.docs.map(doc => ({
        id: doc.id,
        ...doc.data()
      }));
      setData(result);

      // 方式2:实时监听数据变化(如果需要)
      // unsubscribe = onSnapshot(query, (snapshot) => {
      //   const result = snapshot.docs.map(doc => ({
      //     id: doc.id,
      //     ...doc.data()
      //   }));
      //   setData(result);
      // });
    };

    fetchData();

    // 清理函数:组件卸载或依赖变化时取消订阅
    return () => {
      if (unsubscribe) unsubscribe();
    };
  }, [query]); // 关键:将query加入依赖数组,触发重新执行

  return { data, setData, mats, setMats };
}

2. 优化查询传递逻辑(可选但推荐)

每次currPage变化时,query()会创建一个新的对象引用,即使currPage值相同,也可能触发不必要的重请求。你可以直接将currPage作为参数传入useFetch,在Hook内部构建查询,这样依赖项更明确:

修改后的useFetch:

function useFetch(collectionRef, filterField, filterValue) {
  const [data, setData] = useState(null);
  const [mats, setMats] = useState(null);

  useEffect(() => {
    let unsubscribe = null;

    const fetchData = async () => {
      if (!collectionRef || filterValue === undefined) return;
      // 内部构建查询
      const q = query(collectionRef, where(filterField, "==", filterValue));
      const snapshot = await getDocs(q);
      const result = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
      setData(result);
    };

    fetchData();

    return () => {
      if (unsubscribe) unsubscribe();
    };
  }, [collectionRef, filterField, filterValue]); // 依赖是具体的原始值,避免引用变化问题

  return { data, setData, mats, setMats };
}

在Crafts.js中调用:

const { data:crafts, setData:setCrafts, mats, setMats } = useFetch(craftsColRef, "category", currPage);

3. 确认父组件的状态更新逻辑

确保父组件中更新currPage时,是通过React的状态更新函数(比如useState的setter)来触发重渲染,而不是直接修改变量值。例如:

父组件示例:

import { useState } from 'react';
import Crafts from './Crafts';

function ParentComponent() {
  const [currPage, setCurrPage] = useState('default-category');

  const handleNavClick = (category) => {
    setCurrPage(category); // 用setter更新状态,触发子组件重渲染
  };

  return (
    <div>
      <button onClick={() => handleNavClick('woodcraft')}>木工</button>
      <button onClick={() => handleNavClick('pottery')}>陶艺</button>
      <Crafts currPage={currPage} />
    </div>
  );
}

4. 调试验证

可以在Crafts.js和useFetch中添加日志,确认状态变化和查询执行情况:

// Crafts.js中
console.log('当前currPage:', currPage);

// useFetch的useEffect中
console.log('查询已更新,重新获取数据');

内容的提问来源于stack exchange,提问作者glowbo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 08:09:16