Preact Signals全局状态配置报错求助(首次使用useContext)
问题排查与修复
从你的代码和报错情况来看,主要存在以下核心问题,对应修复方案如下:
1. 信号库依赖错误
你当前使用的signals-react-safe是适配React的信号实现,而Preact有官方专属的信号库@preact/signals,混用会导致兼容性问题,这是报错的主要诱因之一。
2. Context消费环节的潜在错误
虽然你配置了Context Provider,但报错大概率是子组件中误用了React的useContext而非Preact的,或者未通过正确方式消费Context。
具体修复步骤
步骤1:替换信号库
先卸载适配React的信号库,安装Preact官方信号:
npm uninstall signals-react-safe npm install @preact/signals
步骤2:修正全局状态文件globalSignal.ts
改用Preact官方信号API,并给Context设置安全默认值,同时封装自定义Hook简化消费:
// Library import { signal } from "@preact/signals"; import { createContext, useContext } from "preact"; // Type // import type * as user from "@/types/user"; export function createAppState() { const session = signal({}); // const userData = signal(null as user.User | null); // const listUser = signal(null as user.ArrUser | null); return { session } } // 设置默认值为null,后续通过自定义Hook做安全校验 export const MyContext = createContext<ReturnType<typeof createAppState> | null>(null); // 封装自定义Hook,避免重复编写校验逻辑 export function useAppState() { const context = useContext(MyContext); if (!context) { throw new Error("useAppState必须在MyContext.Provider内部使用"); } return context; }
步骤3:优化Layout组件
你的layout.tsx代码逻辑没问题,可添加缓存避免重复创建状态实例:
import { ComponentChildren } from "preact"; import Navbar from "./components/Navbar"; import Sidebar from "./components/Sidebar"; import { MyContext, createAppState } from "@/signals/globalSignal"; import { useMemo } from "preact/hooks"; interface Props { children: ComponentChildren; } const DashboardLayout = ({ children }: Props) => { // 用useMemo缓存状态实例,避免每次渲染重复创建 const appState = useMemo(() => createAppState(), []); return ( <MyContext.Provider value={appState}> <div className="flex flex-col max-h-screen h-screen bg-lighterblue"> <Navbar /> <div className="flex flex-auto"> <Sidebar /> <div className="ps-10 w-full"> {children} </div> </div> </div> </MyContext.Provider> ); }; export default DashboardLayout;
步骤4:子组件正确消费全局状态
在需要使用全局状态的子组件中,用封装好的useAppState钩子:
import { useAppState } from "@/signals/globalSignal"; export default function SomeChildComponent() { const { session } = useAppState(); // 读取信号值用session.value,修改直接赋值session.value = 新值 return <div>当前Session: {JSON.stringify(session.value)}</div>; }
额外注意事项
- 确保项目中所有React相关API都从
preact导入(比如import { useState } from "preact"),避免React与Preact的API混用导致冲突。 - 若使用TypeScript,确认
tsconfig.json已正确配置Preact的类型解析路径。
内容的提问来源于stack exchange,提问作者muntun
相关产品推荐
相关产品推荐

