Next.js useContext报错:无法解构赋值右侧值求助
解决Next.js中useContext解构时返回undefined的错误
错误原因
- Middle组件未在Context Provider作用域内:你的
LocalSContext组件虽然内部将Middle包裹在Contexts.Provider中,但如果在项目中直接渲染<Middle />而非<LocalSContext />,Middle会脱离上下文作用域,导致useContext(Contexts)返回undefined,解构时触发错误。 - Context未设置默认值:创建
Contexts时未传入默认值,当组件不在Provider内时,useContext会返回undefined,直接解构会引发类型错误。
修复步骤
1. 确保Middle始终在Provider作用域内
不要直接使用<Middle />,而是通过<LocalSContext />渲染Middle,这样Middle会自动处于上下文覆盖范围内。例如在页面组件(如app/page.tsx)中:
'use client' import { LocalSContext } from '../contexts/LocalSContext'; export default function Home() { return ( <LocalSContext /> ); }
2. 为Context设置默认值
创建Context时传入包含所有属性的默认对象,避免未包裹时解构报错:
const Contexts = createContext({ setTask: () => {}, desc: '', myapp: [], setDesc: () => {}, setType: () => {}, handleAddTodo: () => {}, handleRemoveTodo: (index: number) => {} });
3. 修正上下文组件的闭包问题
将blog对象的创建移到handleAddTodo函数内部,确保每次添加任务时获取最新的state值,同时可选清空输入状态:
const handleAddTodo = () => { if (myapp !== null) { const blog = { type: tyPe, title: task, desc: desc }; setMypp([...myapp, blog]); setDesc(''); setTask(''); setType(''); } };
修正后的完整上下文文件代码
'use client' import { createContext, useEffect, useState } from "react"; import React from 'react' import Middle from "../component/Middle"; // 设置Context默认值,避免未包裹时解构报错 const Contexts = createContext({ setTask: () => {}, desc: '', myapp: [], setDesc: () => {}, setType: () => {}, handleAddTodo: () => {}, handleRemoveTodo: (index: number) => {} }); function LocalSContext() { const [task, setTask] = useState(''); const [tyPe, setType] = useState(''); const [desc, setDesc] = useState(''); // 从localStorage初始化数据,补充默认返回值 const [myapp, setMypp] = useState(() => { if (typeof window !== 'undefined') { return JSON.parse(localStorage.getItem('myApp')) || []; } return []; }) // 确保localStorage操作仅在客户端执行 useEffect(() => { if (typeof window !== 'undefined') { localStorage.setItem('myApp', JSON.stringify(myapp)) } }, [myapp]) // 添加任务:在函数内创建blog对象,获取最新state const handleAddTodo = () => { if (myapp !== null) { const blog = { type: tyPe, title: task, desc: desc }; setMypp([...myapp, blog]); // 清空输入状态 setDesc(''); setTask(''); setType(''); } }; // 删除任务 const handleRemoveTodo = (index: number) => { const newTodos = myapp.filter((_, i) => i !== index); setMypp(newTodos); }; return ( <Contexts.Provider value={{setTask, desc, myapp, setDesc, setType, handleAddTodo, handleRemoveTodo}}> <Middle/> </Contexts.Provider> ) } export {Contexts, LocalSContext}
内容的提问来源于stack exchange,提问作者orgil naranhuu
相关产品推荐
相关产品推荐

