You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:35:58