React.createElement 类型无效 [与其他类似帖子不同的错误]

React.createElement type is invalid [DIFFERENT ERROR FROM OTHER SIMILAR POSTS]

我的困境:一切都正确编译并且 django 服务器运行良好;然而,开发人员工具显示了同样的错误。 注意:堆栈溢出和 github 上还有其他类似的帖子;但是,我已经通读了所有这些内容并尝试了每个建议的答案,但都无济于事! 这是我的错误的屏幕截图:

我的项目是一个 react/django 项目,所以我目前有一个名为“DataGetching.js”的文件,它从我试图在屏幕上显示的 api 中提取信息在我的 App.js 中调用此组件。我正在尝试这样做,同时也在 App.js 中实现一个导航栏,以尝试感受 api 和 React 组件之间的交互,随着我作为开发人员的成长。这是我的 App.js、webpack、index.js、index.html、DataFetching.js、我的文件结构和 package.json.

文件结构:

App.js:

import './index.css';
import { ReactComponent as BellIcon } from './icons/bell.svg';
import { ReactComponent as MessengerIcon } from './icons/messenger.svg';
import { ReactComponent as CaretIcon } from './icons/caret.svg';
import { ReactComponent as PlusIcon } from './icons/plus.svg';
import { ReactComponent as CogIcon } from './icons/cog.svg';
import { ReactComponent as ChevronIcon } from './icons/chevron.svg';
import { ReactComponent as ArrowIcon } from './icons/arrow.svg';
import { ReactComponent as BoltIcon } from './icons/bolt.svg';
import DataFetching from "../DataFetching";
import React, { useState, useEffect, useRef} from 'react';
import { CSSTransition } from 'react-transition-group';



function App() {
  return (
    <div className="App">
      <DataFetching />
      <Navbar>
        <NavItem icon={<PlusIcon />} />
        <NavItem icon={<BellIcon />} />
        <NavItem icon={<MessengerIcon />} />
        <NavItem icon={<CaretIcon />}>
          <DropdownMenu></DropdownMenu>
        </NavItem>
      </Navbar>
    </div>
  );
}


function Navbar(props) {
  return (
    <nav className="navbar">
      <ul className="navbar-nav">{props.children}</ul>
    </nav>
  );
}

function NavItem(props) {
  const [open, setOpen] = useState(false);

  return (
    <li className="nav-item">
      <a href="#" className="icon-button" onClick={() => setOpen(!open)}>
        {props.icon}
      </a>

      {open && props.children}
    </li>
  );
}

function DropdownMenu() {
  const [activeMenu, setActiveMenu] = useState('main');
  const [menuHeight, setMenuHeight] = useState(null);
  const dropdownRef = useRef(null);

  useEffect(() => {
    setMenuHeight(dropdownRef.current?.firstChild.offsetHeight)
  }, [])

  function calcHeight(el) {
    const height = el.offsetHeight;
    setMenuHeight(height);
  }

  function DropdownItem(props) {
    return (
      <a href="#" className="menu-item" onClick={() => props.goToMenu && setActiveMenu(props.goToMenu)}>
        <span className="icon-button">{props.leftIcon}</span>
        {props.children}
        <span className="icon-right">{props.rightIcon}</span>
      </a>
    );
  }

  return (
    <div className="dropdown" style={{ height: menuHeight }} ref={dropdownRef}>

      <CSSTransition
        in={activeMenu === 'main'}
        timeout={500}
        classNames="menu-primary"
        unmountOnExit
        onEnter={calcHeight}>
        <div className="menu">
          <DropdownItem>My Profile</DropdownItem>
          <DropdownItem
            leftIcon={<CogIcon />}
            rightIcon={<ChevronIcon />}
            goToMenu="settings">
            Settings
          </DropdownItem>
          <DropdownItem
            leftIcon=""
            rightIcon={<ChevronIcon />}
            goToMenu="animals">
            Animals
          </DropdownItem>

        </div>
      </CSSTransition>

      <CSSTransition
        in={activeMenu === 'settings'}
        timeout={500}
        classNames="menu-secondary"
        unmountOnExit
        onEnter={calcHeight}>
        <div className="menu">
          <DropdownItem goToMenu="main" leftIcon={<ArrowIcon />}>
            <h2>My Tutorial</h2>
          </DropdownItem>
          <DropdownItem leftIcon={<BoltIcon />}>HTML</DropdownItem>
          <DropdownItem leftIcon={<BoltIcon />}>CSS</DropdownItem>
          <DropdownItem leftIcon={<BoltIcon />}>JavaScript</DropdownItem>
          <DropdownItem leftIcon={<BoltIcon />}>Awesome!</DropdownItem>
        </div>
      </CSSTransition>

      <CSSTransition
        in={activeMenu === 'animals'}
        timeout={500}
        classNames="menu-secondary"
        unmountOnExit
        onEnter={calcHeight}>
        <div className="menu">
          <DropdownItem goToMenu="main" leftIcon={<ArrowIcon />}>
            <h2>Animals</h2>
          </DropdownItem>
          <DropdownItem leftIcon="">Kangaroo</DropdownItem>
          <DropdownItem leftIcon="">Frog</DropdownItem>
          <DropdownItem leftIcon="">Horse?</DropdownItem>
          <DropdownItem leftIcon="">Hedgehog</DropdownItem>
        </div>
      </CSSTransition>
    </div>
  );
}




export default App;

Webpack

module.exports = {
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader"
          }
        },
        {
          test: /\.css$/i,
          use: ["style-loader", "css-loader"],
        },
        {
          test: /\.svg$/,
          use: [
            {
              loader: 'svg-url-loader',
              options: {
              limit: 10000,
              },
            },
          ],
        },
      ]
    }
  };

DataFetching.js

import React, {useState, useEffect} from 'react'
import axios from 'axios'

function DataFetching() {
    const [leads, setLeads] = useState([])

    useEffect(() => {
        axios.get("api/lead")
            .then(res =>{
                console.log(res)
                setLeads(res.data)
            })
            .catch(err => {
                console.log(err)
            })
    }, [])
    return (
        <div>
            <ul>
                {
                    leads.map(lead => <li key={lead.id}>{lead.name} says {lead.message}</li>)
                }
            </ul>
        </div>
    )
}

export default DataFetching

index.js

import App from "./App";
import ReactDOM from 'react-dom';
import './index.css';
import React from "react";

ReactDOM.render(<App />, document.getElementById('root'));

index.html

<!DOCTYPE html>
<html>
<head>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700;900&display=swap" rel="stylesheet">
    <title>React App</title>
</head>
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root">
      <!-- React will load here -->
  </div>
  {% load static %}
  <script src="{% static "frontend/main.js" %}"></script>
</body>

</html>

package.json

{
  "name": "frontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development --entry ./src/index.js --output-path ./static/frontend",
    "build": "webpack --mode production --entry ./src/index.js --output-path ./static/frontend",
    "start": "node server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.13.15",
    "@babel/preset-env": "^7.13.15",
    "@babel/preset-react": "^7.13.13",
    "babel-loader": "^8.2.2",
    "css-loader": "^5.2.1",
    "html-loader": "^2.1.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "style-loader": "^2.0.0",
    "svg-url-loader": "^7.1.1",
    "webpack": "^5.31.2",
    "webpack-cli": "^4.6.0"
  },
  "dependencies": {
    "axios": "^0.21.1",
    "react-transition-group": "^1.2.1"
  }
}

有几处需要更改。将每个 svg 的导入行更改为 import BellIcon from './icons/bell.svg';

然后,在webpack中,改为:

module.exports = {
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader"
          }
        },
        {
          test: /\.css$/i,
          use: ["style-loader", "css-loader"],
        },
        {
          test: /\.svg$/,
          use: [
            {
              loader: 'file-loader',
              options: {
              // name: 'images/[hash]-[name].[ext]',
              },
            },
          ],
        },
      ]
    }
  };

在package.json中,需要添加"bootstrap-icons": "^1.4.1",

最后,在.babelrc中添加一个插件:

"plugins": [ "inline-react-svg" ]