在Deno Fresh中使用reveal.js时触发__hooks空值读取错误求助
问题:Deno Fresh Island中使用useEffect触发"Cannot read properties of null (reading '__hooks')"错误
为了在Deno Fresh中使用reveal.js,我在Island中编写了如下代码:
import { useEffect } from "https://esm.sh/v128/preact@10.19.6/hooks/src/index.js"; import Reveal from '../reveal/js/index.js'; export default function Island() { useEffect(()=> { setDeck(new Reveal()); deck.initialize(); }) return <>Text</> }
我认为这是正确使用useEffect钩子的方式,但却触发了如下错误:
An error occurred during route handling or page rendering. 3 | 4 | export default function Island() { > 5 | useEffect(()=> { | ^ 6 | newFunction(); 7 | 8 | function newFunction() { TypeError: Cannot read properties of null (reading '__hooks') at s (https://esm.sh/stable/preact@10.19.6/denonext/hooks/src.js:2:1339) at G (https://esm.sh/stable/preact@10.19.6/denonext/hooks/src.js:2:2385) at Object.Island (file:///D:/Programming/Test/fresh-project/islands/Island.jsx:5:3) at m (https://esm.sh/v135/preact-render-to-string@6.3.1/X-ZS8q/denonext/preact-render-to-string.mjs:2:3237) at m (https://esm.sh/v135/preact-render-to-string@6.3.1/X-ZS8q/denonext/preact-render-to-string.mjs:2:2543) at m (https://esm.sh/v135/preact-render-to-string@6.3.1/X-ZS8q/denonext/preact-render-to-string.mjs:2:3802) at m (https://esm.sh/v135/preact-render-to-string@6.3.1/X-ZS8q/denonext/preact-render-to-string.mjs:2:3802) at m (https://esm.sh/v135/preact-render-to-string@6.3.1/X-ZS8q/denonext/preact-render-to-string.mjs:2:3802) at m (https://esm.sh/v135/preact-render-to-string@6.3.1/X-ZS8q/denonext/preact-render-to-string.mjs:2:3802) at m (https://esm.sh/v135/preact-render-to-string@6.3.1/X-ZS8q/denonext/preact-render-to-string.mjs:2:3802)
错误原因分析
这个错误的核心原因有两个:
Preact Hooks导入路径错误:你直接导入了preact hooks的源码文件(
hooks/src/index.js),而非适配Deno环境的预构建版本。这种导入方式会导致Hooks无法正确关联Preact组件上下文,服务端渲染时找不到__hooks对象。代码存在未定义变量问题:代码中的
setDeck和deck未声明,即便解决Hooks的问题,后续也会抛出变量未定义的错误。
另外,useEffect未传递依赖数组,会导致组件每次渲染都重复执行effect,这属于潜在的性能问题。
修正后的代码
// 使用适配Deno的Preact Hooks导入路径 import { useEffect, useState } from "https://esm.sh/preact@10.19.6/hooks"; import Reveal from '../reveal/js/index.js'; export default function Island() { // 用useState存储reveal实例 const [deck, setDeck] = useState(null); useEffect(()=> { // 初始化reveal实例 const newDeck = new Reveal(); newDeck.initialize(); setDeck(newDeck); // 组件卸载时销毁实例,避免内存泄漏 return () => { newDeck.destroy(); }; }, []); // 空依赖数组确保effect仅执行一次 return <>Text</> }
额外说明
Deno Fresh的Islands会先执行服务端渲染,而reveal.js是纯客户端库,useEffect在服务端渲染阶段不会运行,因此把初始化逻辑放在effect里是安全的,能确保代码仅在客户端执行。
内容的提问来源于stack exchange,提问作者Ooker
相关产品推荐
相关产品推荐

