reactjs - 是否可以在不使用 JSX 的情况下使用 React Hooks API(在 typescript 中)

标签 reactjs typescript react-hooks jsx

翻译 JSX 版本 React Hooks API 时 demo进入没有 JSX 的一个,如下 react-without-jsx ,我得到了以下代码

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

export function test() {
  ReactDOM.render(Count(), document.getElementById('main'));
}

export function Count() {
  const e = React.createElement;
  const [count, setCount] = useState(0);
  const button = e('button', {
    onClick: () => {
      setCount(count + 1);
    },
  });
  return e('div', null, e('p', `You clicked ${count} times`), button);
}

但是,当在浏览器中运行此代码时,我收到以下错误

react.development.js:1551 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/warnings/invalid-hook-call-warning.html for tips about how to debug and fix this problem.
    at resolveDispatcher (react.development.js:1551)
    at Object.useState (react.development.js:1582)
    at Count (Count.ts:10)
    at Object.test (Count.ts:5)
    at main (index.ts:4)
    at Object../src/index.ts (index.ts:6)
    at __webpack_require__ (bootstrap:19)
    at bootstrap:83
    at bootstrap:83
resolveDispatcher @ react.development.js:1551
useState @ react.development.js:1582
Count @ Count.ts:9
test @ Count.ts:4
main @ index.ts:3
./src/index.ts @ index.ts:6
__webpack_require__ @ bootstrap:18

如果使用 JSX,上面的示例可以正常工作。

所有功能组件的示例似乎都是基于 JSX 的。 那么是否可以在没有 JSX 的情况下使用 React Hook 呢?如果可以的话,我们怎样才能做到呢?


编辑更新:上面的代码仍然有错误(如以下编辑所述)。

e('p', `You clicked ${count} times`)

应该是

e('p', null, `You clicked ${count} times`)

createElement 的第二个参数应该是 props。


按照@qxg的说明进行编辑。

在渲染过程中,我没有使用React.createElement,通过将代码修改为

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

export function test() {
  ReactDOM.render(React.createElement(Count), document.getElementById('main'));
}

// ... Same code for Count as above

函数组件外部调用Hooks API错误已解决!

但是,出现了新的错误,例如:

Warning: Invalid attribute name: `0`    react-dom.development.js:82
    in p (created by Count)
    in div (created by Count)
    in Count
Warning: Invalid attribute name: `1`    react-dom.development.js:82
    in p (created by Count)
    in div (created by Count)
    in Count

很多像上面这样的错误,以

结尾
Warning: Invalid attribute name: `18`   react-dom.development.js:82 
    in p (created by Count)
    in div (created by Count)
    in Count

页面呈现为

<div>
  <p></p>
  <button></button>
</div>

因此只有空元素,没有文本。 对于这个问题有什么建议吗?


附:我不确定是否存在 typescript/webpack 的配置错误,所以我将其发布在这里。

ts.config.json

{
  "compilerOptions": {
    "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    "lib": [
      "DOM",
      "DOM.Iterable",
      "ESNext"
    ] /* Specify library files to be included in the compilation. */,
    "jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,
    "sourceMap": true /* Generates corresponding '.map' file. */,
    "outDir": "./dist" /* Redirect output structure to the directory. */,
    "strict": true /* Enable all strict type-checking options. */,
    "noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
    "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,

    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,

    "skipLibCheck": true /* Skip type checking of declaration files. */,
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  }
}

webpack.config.js

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.ts',
  // Enable sourcemaps for debugging webpack's output.
  devtool: 'source-map',

  resolve: {
    // Add '.ts' and '.tsx' as resolvable extensions.
    extensions: ['.ts', '.tsx'],
  },

  module: {
    rules: [
      {
        test: /\.ts(x?)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'ts-loader',
          },
        ],
      },
      // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
      {
        enforce: 'pre',
        test: /\.js$/,
        loader: 'source-map-loader',
      },
    ],
  },
  externals: {
    react: 'React',
    'react-dom': 'ReactDOM',
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
  </head>
  <body>
    <div id="main"></div>
    <script src="./node_modules/react/umd/react.development.js"></script>
    <script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
    <!-- Main -->
    <script src="./dist/bundle.js"></script>
  </body>
</html>

最佳答案

您手动将 jsx 转换为 React.creatEelement,但也忘记转换顶级元素。

ReactDOM.render(React.createElement(Count), document.getElementById('main'));

关于reactjs - 是否可以在不使用 JSX 的情况下使用 React Hooks API(在 typescript 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61862140/

相关文章:

reactjs - Apollo GraphQl 存储派生数据

javascript - useMemo 与 useEffect + useState

javascript - 如何使用 React.useRef 获取实际的 Dom 节点? Element.getBoundingClientRect() 不适用于 useRef 变量

javascript - keyCode 返回 'undefined' ( react )

javascript - Material-UI Select,如何应用 :focus-within styling on the select when the input is clicked?

javascript - React 组件的 Material UI 主题不局限于 Shadow DOM

Angular 4 使用 viewChildran 在动态生成的文本框中设置焦点

javascript - 在通常放置 var 的地方使用 type 关键字是什么?

typescript - 如何使用 bcrypt 模块使用 NestJS 在 MongoDB 中保存加密密码

javascript - React.memo 不适用于功能组件和谷歌地图