简体   繁体   English

Webpack 外部反应导致 React Hooks 错误

[英]Webpack external react causes React Hooks Error

I am the author of FireJS .我是FireJS的作者。 I am encountering an issue with react hooks.我遇到了反应钩子的问题

(node:21793) UnhandledPromiseRejectionWarning: 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 (webpack://%5Bname%5D/./node_modules/react/cjs/react.development.js?:1465:13)
    at useState (webpack://%5Bname%5D/./node_modules/react/cjs/react.development.js?:1496:20)
    at Header (webpack://__FIREJS_APP__/./src/pages/404.js?:22:73)
    at processChild (/media/dedsec/Data/Projects/FireJS/node_modules/react-dom/cjs/react-dom-server.node.development.js:3043:14)
    at resolve (/media/dedsec/Data/Projects/FireJS/node_modules/react-dom/cjs/react-dom-server.node.development.js:2960:5)
    at ReactDOMServerRenderer.render (/media/dedsec/Data/Projects/FireJS/node_modules/react-dom/cjs/react-dom-server.node.development.js:3435:22)
    at ReactDOMServerRenderer.read (/media/dedsec/Data/Projects/FireJS/node_modules/react-dom/cjs/react-dom-server.node.development.js:3373:29)
    at Object.renderToString (/media/dedsec/Data/Projects/FireJS/node_modules/react-dom/cjs/react-dom-server.node.development.js:3988:27)
    at /media/dedsec/Data/Projects/FireJS/dist/architects/StaticArchitect.js:51:36
    at default_1.render (/media/dedsec/Data/Projects/FireJS/dist/architects/StaticArchitect.js:57:11)
    at /media/dedsec/Data/Projects/FireJS/dist/FireJS.js:99:143
    at default_1.<anonymous> (/media/dedsec/Data/Projects/FireJS/dist/classes/Plugin.js:20:13)
    at Generator.next (<anonymous>)
    at /media/dedsec/Data/Projects/FireJS/dist/classes/Plugin.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/media/dedsec/Data/Projects/FireJS/dist/classes/Plugin.js:4:12)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:21793) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:21793) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I've double-checked each and every suggestion given in the help page , but I am unable to resolve the issue.我已经仔细检查帮助页面中给出的每一个建议,但我无法解决这个问题。

I am bundling react as an external chunk and then using it as a library.我将 react 捆绑为外部块,然后将其用作库。 Here's a snapshot of my webpack config ;这是我的webpack 配置的快照;

            target: 'web',
            mode: this.$.config.pro ? "production" : "development",
            entry: {
                "React": "react",
                "ReactDOM": "react-dom",
                "ReactHelmet": "react-helmet",
            },
            output: {
                path: this.$.config.paths.lib,
                filename: "e[contentHash].js",
                library: "[name]",//make file as library so it can be imported for static generation
                libraryTarget: "window"
            }
        mergedConfig.externals["react"] = 'React';
        mergedConfig.externals["react-dom"] = "ReactDOM";
        mergedConfig.externals["react-helmet"] = "ReactHelmet";
        const cssLoaderUse = [MiniCssExtractPlugin.loader,
            {
                loader: 'css-loader',
                options: {
                    modules: {
                        hashPrefix: 'hash',
                    },
                },
            }
        ];
        mergedConfig.module.rules.push({
                test: /\.(js|jsx)$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ["@babel/preset-env", "@babel/preset-react"]
                    }
                },
            }, {
                test: /\.sass$/i,
                loader: [...cssLoaderUse, 'sass-loader']
            }, {
                test: /\.less$/i,
                loader: [...cssLoaderUse, 'less-loader']
            }, {
                test: /\.css$/i,
                use: cssLoaderUse
            }
        );

I am exporting it as window.__FIREJS_APP__我将其导出为window.__FIREJS_APP__

        mergedConfig.output.library = "__FIREJS_APP__";
        mergedConfig.output.libraryTarget = "window";

The react file I am trying to run我试图运行的反应文件

import React, { useState } from 'react';

export default() => {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Rendering process渲染过程

runApp: function (func = ReactDOM.render) {
        func(React.createElement(window.__FIREJS_APP__.default, {content: window.__MAP__.content}),
            document.getElementById("root")
        );
    }

if (window.__SSR__)
    LinkApi.runApp(ReactDOM.hydrate)
else
    LinkApi.runApp()

Why do I think this is a webpack issue?为什么我认为这是 webpack 问题?

Previously, when I bundled the files normally, React Hooks worked flawlessly but when I switched to external react.以前,当我正常捆绑文件时,React Hooks 工作完美,但当我切换到外部反应时。 React Hooks started to cause this issue. React Hooks 开始导致这个问题。

I figured out how to fix this issue.我想出了如何解决这个问题。 You need to bundle react , react-dom and react-dom/server to the same bundle.您需要将reactreact-domreact-dom/server捆绑到同一个包中。

Eg:例如:

window.React = require("react");
window.ReactDOM = require("react-dom")
window.ReactDOMServer = require("react-dom/server")

Bundle the above file and import it as your first script.捆绑上述文件并将其作为您的第一个脚本导入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM