开发Raycast扩展遇React报错:Rendered more hooks than during the previous render
问题原因
你遇到的报错是因为违反了React Hook的核心规则:Hook必须在组件的每次渲染中按完全相同的顺序调用。原代码里把useSQL放在try/catch块内,且仅在ready为true时尝试赋值,这会导致组件首次渲染(数据库未准备好)和后续渲染(ready变为true)时,Hook的调用数量/顺序不一致,触发React的Hook校验错误。
修复方案
核心思路是:确保useSQL在每次渲染时都被调用,用状态控制是否使用它返回的数据,而非条件性调用Hook。
修改后的代码如下:
import { useState, useEffect } from "react"; import { useSQL } from "@raycast/utils"; export const useSqlNote = <NoteItem>(query: string) => { const [ready, setReady] = useState<boolean>(false); // 把useSQL移到最外层,确保每次渲染都按固定顺序调用,符合Hook规则 const { data: sqlData, isLoading: sqlLoading, permissionView, error } = useSQL<NoteItem>(PATH, query); useEffect(() => { // 数据库初始化仅需执行一次,依赖数组设为空 const initDB = async () => { await create_or_update_db(); setReady(true); }; initDB(); }, []); // 若业务需要随query变化重建数据库,可将query加入依赖数组 // 根据ready状态决定返回内容 if (!ready) { // 数据库未就绪时,返回初始化中的加载状态 return { data: [], isLoading: true, errorView: undefined }; } // 数据库就绪后,返回useSQL的实际数据 return { data: sqlData || [], isLoading: sqlLoading, errorView: permissionView || error }; };
关键修改点
- 固定Hook调用顺序:将
useSQL移到组件最顶层,保证每次渲染都按相同顺序调用Hook,彻底解决顺序错误问题。 - 优化初始化逻辑:
useEffect依赖数组改为空数组,数据库初始化仅执行一次(需随query更新数据库时再添加query到依赖)。 - 状态控制数据返回:用
ready状态判断数据库是否就绪,未就绪时返回默认加载状态,就绪后返回useSQL的真实数据。 - 简化错误处理:直接使用
useSQL返回的permissionView和error,无需用try/catch包裹Hook调用(Hook内部已处理自身错误)。
内容的提问来源于stack exchange,提问作者Arnaud Lewandowski
相关产品推荐
相关产品推荐

