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
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"));