[英]How to use useState hook with Preact and no build tools?
Currently I need to get a Preact application working without any build tools, just with an index.html with the import statements to get preact from the CDN.目前,我需要让 Preact 应用程序在没有任何构建工具的情况下工作,只需使用带有 import 语句的 index.html 从 CDN 获取 preact。 I'm able to import the
useState
hook from the CDN no problem, and even able to console.log() the value of the function useState
, but whenever I try to use it, I get an error saying:我可以从 CDN 导入
useState
钩子没有问题,甚至可以 console.log() 函数useState
的值,但是每当我尝试使用它时,我都会收到一条错误消息:
'Uncaught TypeError: u is undefined' '未捕获的类型错误:你未定义'
Do ya'll happen to know why this is the case?你会碰巧知道为什么会这样吗? I have tried to use the
useState
function inside of the functional component, and outside and it doesn't work either way.我尝试在功能组件内部和外部使用
useState
函数,但无论哪种方式都不起作用。 Am I missing something here?我在这里错过了什么吗? Can anyone help point me in the right direction?
谁能帮我指出正确的方向?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="module">
import { h, Component, render } from 'https://unpkg.com/preact?module';
import { useState } from 'https://unpkg.com/preact@latest/hooks/dist/hooks.module.js?module'
import htm from 'https://unpkg.com/htm?module';
// Initialize htm with Preact
const html = htm.bind(h);
const App = (props) => {
const [testVar, setTestVar] = useState(0);
var countVariable = 0;
const incrementButtonHandler = () => {
countVariable = countVariable + 1;
}
const logMethod = () => {
console.log(countVariable);
countVariable = countVariable + 1;
}
return html`<div>
<h1>Test ${props.name}!: ${countVariable}</h1>
<button onClick=${logMethod}>Increment</button>
</div>`;
}
render(html`<${App} name="World" />`, document.body);
</script>
</head>
<body>
</body>
</html>
This is a known bug and limitation in what unpkg can do, see: https://github.com/preactjs/preact/issues/2571这是 unpkg 可以做的已知错误和限制,请参阅: https ://github.com/preactjs/preact/issues/2571
There's a couple easy fixes though:不过有几个简单的修复方法:
@latest
in the preact import)@latest
导入中的 @latest)import { h, render } from 'https://unpkg.com/preact@latest?module'
import { useState } from 'https://unpkg.com/preact@latest/hooks/dist/hooks.module.js?module'
import { html } from 'https://unpkg.com/htm/preact/index.module.js?module'
import { h, render } from 'https://cdn.skypack.dev/preact';
import { useState } from 'https://cdn.skypack.dev/preact/hooks';
import { html } from 'https://cdn.skypack.dev/htm/preact';
Either should work.要么应该工作。
rchristian's answer is useful, but the module-imported hooks appear to fail when using a router. rchristian 的回答很有用,但是在使用路由器时,模块导入的钩子似乎失败了。 Here's a minimal repro*.
这是一个最小的复制*。
(If you have trouble navigating to the /about
route in the snippets, you may need to run them locally since the iframe doesn't play well with routing on all browsers, notably Chrome at the time of writing.) (如果您在导航到代码片段中的
/about
路由时遇到问题,您可能需要在本地运行它们,因为 iframe 在所有浏览器上都不能很好地支持路由,尤其是在撰写本文时的 Chrome。)
<script type="module"> import {h, render, Component} from "https://cdn.skypack.dev/preact"; import {useState} from "https://cdn.skypack.dev/preact/hooks"; import {Router} from "https://cdn.skypack.dev/preact-router"; import htm from "https://cdn.skypack.dev/htm"; const html = htm.bind(h); const Counter = () => { const [count, setCount] = useState(0); const increment = () => { setCount(prevState => prevState + 1); }; return html` <button onClick=${increment}> Count: ${count} </button> `; }; const Nav = () => html` <nav> <a href="/">home</a> | <a href="/about">about</a> </nav> `; const Home = () => html` <p>Home</p> <${Counter} /> `; const About = () => html` <p>About</p> `; const App = () => html` <header> <${Nav} /> </header> <main> <${Router}> <${Home} path="/" /> <${About} path="/about" /> <${Home} default /> <//> </main> `; render(html`<${App} />`, document.querySelector("#app")); </script> <div id="app"></div>
Starting at the home route, you'll see the counter component works fine.从主路由开始,您会看到计数器组件工作正常。 Navigate to the about route, then back to home and you'll see
Uncaught (in promise) TypeError: u is null
from the hooks script.导航到 about 路线,然后返回 home,你会看到
Uncaught (in promise) TypeError: u is null
from the hooks 脚本。
I'd much prefer the module imports so I'd be curious to hear how to fix the above code, but I did manage to work around this with the following UMD approach:我更喜欢模块导入,所以我很想知道如何修复上述代码,但我确实设法使用以下 UMD 方法解决了这个问题:
<script type="module"> const {h, render, Component} = preact; const {useState, useEffect} = preactHooks; const {Router} = preactRouter; import htm from "https://cdnjs.cloudflare.com/ajax/libs/htm/3.1.1/htm.module.js"; const html = htm.bind(h); const Counter = () => { const [count, setCount] = useState(0); const increment = () => { setCount(prevState => prevState + 1); }; return html` <button onClick=${increment}> Count: ${count} </button> `; }; const Nav = () => html` <nav> <a href="/">home</a> | <a href="/about">about</a> </nav> `; const Home = () => html` <p>Home</p> <${Counter} /> `; const About = () => html` <p>About</p> `; const App = () => html` <header> <${Nav} /> </header> <main> <${Router}> <${Home} path="/" /> <${About} path="/about" /> <${Home} default /> <//> </main> `; render(html`<${App} />`, document.querySelector("#app")); </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/preact/10.7.2/preact.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/preact/10.7.2/hooks.umd.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/preact-router/4.0.1/preact-router.umd.min.js"></script> <div id="app"></div>
This is similar to Jason Miller's Router example but also uses hooks.这类似于Jason Miller 的路由器示例,但也使用了钩子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.