不能使用带有打字稿的反应钩子

Cant use react hooks with typescript

我正在使用打字稿将源 tsx 文件编译为 js

tsx 文件中的源代码正确使用了 react hooks,编译后的版本似乎也正确使用了它们。

源代码 (tsx)

import React, { useEffect } from "react";

export function Checkbox() : JSX.Element {
    useEffect(function() {
        console.log("Component mounted!");
    });

    return (
        <div>...</div>
    );
}

编译为 (js)

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Checkbox = void 0;
var jsx_runtime_1 = require("react/jsx-runtime");
var react_1 = require("react");
function Checkbox() {
    react_1.useEffect(function () {
        console.log("Component mounted!");
    });
    return (jsx_runtime_1.jsx("div", { children: "..." }, void 0));
}
exports.Checkbox = Checkbox;
//# sourceMappingURL=Checkbox.js.map

tsconfig.json

{
    "$schema": "http://json.schemastore.org/tsconfig",
    "compilerOptions": {
        "lib": ["es2020", "dom"],
        "module": "commonjs",
        "target": "es5",
        "baseUrl": "src/ts",
        "types": ["node", "react"],
        "jsx": "react-jsx",
        "outDir": "src/js",
        "sourceMap": true,
        "strict": true,
        "allowJs": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "noUnusedParameters": true,
        "allowUnreachableCode": false,
        "preserveConstEnums": false,
        "resolveJsonModule": true
    },
    "include": ["src/ts/**/*"]
}

我在 chrome 控制台中收到以下错误,说我违反了挂钩规则。

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    at resolveDispatcher (react.development.js?52c0:1476)
    at Object.useEffect (react.development.js?52c0:1519)
    at Checkbox (Checkbox.tsx?7b6e:4)
    at renderWithHooks (react-dom.development.js?61bb:14985)
    at mountIndeterminateComponent (react-dom.development.js?61bb:17811)
    at beginWork (react-dom.development.js?61bb:19049)
    at HTMLUnknownElement.callCallback (react-dom.development.js?61bb:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js?61bb:3994)
    at invokeGuardedCallback (react-dom.development.js?61bb:4056)
    at beginWork (react-dom.development.js?61bb:23964)

我已经在谷歌上搜索了几天,但仍然不知道为什么会这样...

我真的很想第一个 jsx_runtime 的名字是 jsx_runtime_0 甚至如果只有一个 jsx_runtime 那么它的后缀是全部由打包机完成!

这不是证据,但它让我推测你是否真的有两个版本的 React,因为你包含在项目中的两个模块中的每一个都将其声明为依赖项(而不是对等依赖项),因此有他们在捆绑包中引用的自己的副本。

由于 React 的每个副本都使用不同的闭包来存储顶级内容,这意味着它会注意到,例如useState 在 React 的不同副本的上下文中被调用。

我已经根据您的问题创建了一个 CodeSandBox:Codesandbox

一个简单的方法是这样使用:

TSX 中的源代码

import React, { useEffect } from "react";

const Checkbox = (props) => {
  useEffect(() => {
    console.log("Component mounted!");
  }, []); // https://reactjs.org/docs/hooks-effect.html

  return <div>Checkbox</div>;
};

export default Checkbox;

函数组件returns一个JSX.Element。

在这个link里面还有关于JSX的解释:Introducing JSX