Search code examples
reactjsdjangowebpackcompilationbabel-loader

Webpack/babel not compiling ReactDOM.render


Objective: I am trying to get webpack/babel to compile JSX so that I can make a website with react front end, and django rest api backend. I have gone through many tutorials and Stackoverflows, but never gotten JSX to compile to make combo work.

I debugged for a LONG time, and found that the crux of the JSX problem seems to be centered around reactDOM.render. If I use react components without reactDOM.render, it all works, with is breaks down with errors such as

"App.js:12 Uncaught ReferenceError: ReactDOM is not defined" or the one I get most often, "Module parse failed: Unexpected token (13:12) You may need an appropriate loader to handle this file type"

here is the code-- my .babelrc file:

{
    "presets": [
        "@babel/preset-env", "@babel/preset-react"
    ]
}

webpack.config.js:

module.exports = {
    module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader"
          }
        }
      ]
    }
  };

packages.json:

    {
  "name": "frontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack --mode development --entry ./src/index.js --output-path ./static/frontend",
    "build": "webpack --mode production --entry ./src/index.js --output-path ./static/frontend"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.14.6",
    "@babel/preset-env": "^7.14.7",
    "@babel/preset-react": "^7.14.5",
    "babel-loader": "^8.2.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "webpack": "^5.42.1",
    "webpack-cli": "^4.7.2"
  }
}

index.html inside of "templates/frontend":

  <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>Django REST with React</title>
    </head>
    <body>
    <div id="app">
        <!-- React will load here -->
    </div>
    </body>
    {% load static %}
    <script src="{% static 'frontend/main.js' %}"></script>
    </html>

index.js located at './scr/index.js':

import App from "./components/App";

..and because I am using Django I also have a urls.py that points to a view, and here is my view:

from django.shortcuts import render


def index(request):
    return render(request, 'frontend/index.html')

its worth noting that I have installed this app into the settings of Django, as well as the restAPI framework, which sits on the backend app. I have testing the api seperate and it works, I have gone to the api page, and I have seen the api talk to non-react components. The urls.py for the whole project by-default points the user to frontend/urls.py via include(), this has also been tested and works.

I THOUGHT I solved the babel/webpack/JSX problem, but I realized that while this works perfectly, nothing is rendered to the DOM. [my actual code used the data fetch but this post simplifies my code] (code that words for './src/components/App.js'):

import React, { Component } from "react";
import { render } from "react-dom";

class App extends Component {
  render() {
    return (
      <p>hello world</p>
    );
  }
}

export default App;

const container = document.getElementById("app");
render(<App />, container);

this works, no problems! if I instead, try to render it to the DOM, it throws an error:

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  <p>hello world</p>,
  document.getElementById('root')
);

maybe I need to write it more elegently? same error if I write it this way:

import React, { Component } from "react";
import { render } from "react-dom";


class App extends Component{
    render() {
        return(
            <p>hello world</p>
        );
    }
};

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

It threw this error this time (sometimes I see the other one about lacking appropriate loader):

App.js:55 Uncaught ReferenceError: ReactDOM is not defined
    at eval (App.js:55)
    at Object../src/components/App.js (main.js:19)
    at __webpack_require__ (main.js:143)
    at eval (index.js:2)
    at Object../src/index.js (main.js:29)
    at __webpack_require__ (main.js:143)
    at main.js:183
    at main.js:185

Spent long time staring at this issue and browsing stack overflow, and tried my best to format this stack post cleanly necessary information, thanks for your help


Solution

  • The error tells you ReactDOM is not defined. It's because you never import ReactDOM. You only import render. So write:

    import * as React from "react";
    import ReactDOM from "react-dom";
    import App from "./app";
    
    ReactDOM.render <App />, document.getElementById("root"));