使用Prisma与PostgreSQL时hobbies不可迭代错误排查
问题描述
我是Prisma和React新手,PostgreSQL数据库能正常运行,想在应用里展示存储的数据。我的schema里Hobby模型如下:
model Hobby { id Int @id @default(autoincrement()) title String }
我用useContext分发createHobby功能,上下文文件代码如下:
export async function getServerSideProps() { const hobbies: Prisma.HobbyUncheckedCreateInput[] = await prisma.hobby.findMany(); return { props: {initialHobbies: hobbies}, }; } export const HobbyContext = createContext({}) function Provider({ children, initialHobbies }){ const [hobbies, setHobbies] = useState<Prisma.HobbyUncheckedCreateInput[]>(initialHobbies); const createHobby = async (title) => { const body: Prisma.HobbyCreateInput = { title, }; await fetcher("/api/create-hobby", {hobby : body}); console.log(hobbies); const updatedHobbies = [ ...hobbies, body ]; setHobbies(updatedHobbies); const contextData = { hobbies, createHobby, } return ( <HobbyContext.Provider value={contextData}> {children} </HobbyContext.Provider> ); }; export default HobbyContext; export {Provider};
现在出现错误:Uncaught (in promise) TypeError: hobbies is not iterable at createHobby,指向代码const updatedHobbies = [...hobbies, body];。
另外我有个HobbyCreate.tsx组件,通过表单提交创建展示hobby标题的卡片,代码如下:
function HobbyCreate({updateModalState}) { const [title, setTitle] = useState(''); const {createHobby} = useHobbiesContext(); const handleChange = (event) => { setTitle(event.target.value) }; const handleSubmit = (event) => { event.preventDefault(); createHobby(title); }; return ( ... <form onSubmit={handleSubmit}></form> ... )
我不确定问题出在哪,怀疑是创建const [hobbies, setHobbies]并使用initialHobbies时出了问题。
错误分析与修复方案
核心原因
hobbies is not iterable表明你尝试展开的hobbies不是数组类型,可能的触发点:
initialHobbies初始值不是数组(比如查询失败返回null/undefined)- Context默认值为空对象,组件在Provider外调用时拿到
undefined的hobbies - 代码存在语法错误(比如
createHobby函数未闭合大括号)
具体修复步骤
兜底initialHobbies的数组类型
在Provider组件给initialHobbies设置默认空数组,避免传入非数组值:function Provider({ children, initialHobbies = [] }){ const [hobbies, setHobbies] = useState<Prisma.HobbyUncheckedCreateInput[]>(initialHobbies); // 后续代码 }同时在
getServerSideProps里增加错误捕获,确保返回数组:export async function getServerSideProps() { try { const hobbies = await prisma.hobby.findMany(); return { props: { initialHobbies: hobbies || [] } }; } catch (err) { console.error(err); return { props: { initialHobbies: [] } }; } }修正Context默认值结构
给Context设置符合业务逻辑的默认值,避免组件误用时报错:export const HobbyContext = createContext<{ hobbies: Prisma.HobbyUncheckedCreateInput[]; createHobby: (title: string) => Promise<void>; }>({ hobbies: [], createHobby: async () => {} })修复状态更新与语法错误
- 补上
createHobby缺失的闭合大括号,避免语法错误 - 使用函数式更新获取最新状态,避免闭包导致的旧值问题:
const createHobby = async (title) => { const body: Prisma.HobbyCreateInput = { title }; await fetcher("/api/create-hobby", { hobby: body }); // 函数式更新确保拿到最新的hobbies状态 setHobbies(prevHobbies => [...prevHobbies, body]); }; // 补上这个闭合大括号- 补上
完善自定义Hook的校验
确保useHobbiesContext只能在Provider内部使用:export function useHobbiesContext() { const context = useContext(HobbyContext); if (!context) { throw new Error("useHobbiesContext必须在HobbyContext.Provider内部使用"); } return context; }
额外建议
- 开发时查看
console.log(hobbies)的输出,确认它的实际类型,快速定位问题 - 给所有状态和Context值加上严格的TypeScript约束,提前发现类型不匹配问题
内容的提问来源于stack exchange,提问作者BZB
相关产品推荐
相关产品推荐

