是否可以不使用JSX而使用React Hooks API(在打字稿中)

时间:2020-05-18 03:48:05

标签: reactjs typescript react-hooks jsx

在将demo转换为JSX版本的React Hooks API react-without-jsx而不使用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的第二个参数应该是道具。


按照@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>

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


p.s。我不确定是否存在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>

1 个答案:

答案 0 :(得分:2)

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

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