从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
相关产品推荐
相关产品推荐

