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

从JSON取数后返回数组给其他组件时遇Hook渲染错误,如何修复?

错误原因分析

错误 "Rendered fewer hooks than expected. This may be caused by an accidental early return statement." 是因为你违反了React Hooks的核心调用规则:所有Hooks必须在组件的顶层渲染阶段按固定顺序调用,不能在条件判断、循环,或者非组件/自定义Hook的上下文里执行Hook调用。

你的Products是一个标准React组件(使用了useState和useEffect),但在Main组件里,你把它直接当作普通值传入useState的初始值:const[data, setState] = useState(Products);。这相当于在useState的初始化逻辑中直接执行了Products组件的代码——这种场景下React无法正确追踪Hooks的调用链路,自然会抛出错误。


修复方案

方案1:将Products改造成自定义Hook

自定义Hook是React官方推荐的复用状态逻辑的方式,它可以直接返回数据,完美匹配你“获取数组并给其他组件使用”的需求。

修改Products为自定义Hook(重命名为useProducts)

import { useEffect, useState } from "react";

// 自定义Hook必须以use开头,这是React的约定
const useProducts = () => {
  const[products, setProducts] = useState([]);
    
  useEffect(() => {
    const fetchProducts = async () => {
      const response = await fetch('https://camera-store-60351-default-rtdb.firebaseio.com/Products.json');
      const responseData = await response.json();

      const loadProducts = [];
      for (const key in responseData) {
        loadProducts.push({
          id: key,
          title: responseData[key].title,
          category: responseData[key].category,
          img: responseData[key].img,
          price: responseData[key].price,
        });
      }
      setProducts(loadProducts);
    };

    fetchProducts();
  }, []);
    
  return products;
}

export default useProducts;

修改Main组件使用自定义Hook

import Content from "./Content"
import useProducts from "../store/useProducts"

const Main = () => {
  // 在组件顶层直接调用自定义Hook获取数据
  const products = useProducts();

  return (
    <div className="row  my-4 mx-2">
      <Content array={products} />
    </div>    
  )
};

export default Main

方案2:将Products作为组件传递数据

如果你想保留Products作为组件的形式,可以通过子组件回调的方式传递数据:

修改Products组件

import { useEffect, useState } from "react";

const Products = ({ children }) => {
  const[products, setProducts] = useState([]);
    
  useEffect(() => {
    const fetchProducts = async () => {
      const response = await fetch('https://camera-store-60351-default-rtdb.firebaseio.com/Products.json');
      const responseData = await response.json();

      const loadProducts = [];
      for (const key in responseData) {
        loadProducts.push({
          id: key,
          title: responseData[key].title,
          category: responseData[key].category,
          img: responseData[key].img,
          price: responseData[key].price,
        });
      }
      setProducts(loadProducts);
    };

    fetchProducts();
  }, []);
    
  // 通过回调将数据传递给子组件
  return children(products);
}

export default Products;

修改Main组件的使用方式

import Content from "./Content"
import Products from "../store/Products"

const Main = () => {
  return (
    <Products>
      {(products) => (
        <div className="row  my-4 mx-2">
          <Content array={products} />
        </div>
      )}
    </Products>    
  )
};

export default Main

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:58:21