5

I want to add just React components to Django's template html file (not replace entire template with React as Frontend that there are a lot of tutorial on internet, just certain part of website) because that part of website require high interactivity which is easier to write it in React.

I followed Add React to a Website tutorial to add JSX preprocessor. I set up project like this.

/app-a
    /static
        /app-a  <-- preprocessed files are here
    /templates
        /app-a
            index.html  <-- Django template file that I want to include a react component to
/app-b
/react  <-- this is where I wrote JSX files
manage.py
package.json

And included React files at the end of index.html file like this.

<html>
    <body>
        <div id="formContainer">
        </div>
        <!-- React -->
        <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
        <!-- my root React component file -->
        <script src="{% static 'app-a/App.js' %}"></script>

    </body>

And I ran babel --watch to preprocess JSX files like this
npx babel --watch ./react --out-dir ./app-a/static/app-a --presets react-app
I thought it worked because whenever I saved JSX component files, they were preprocessed and output to /app-a/static/app-a.

At the end of root JSX file, I included root React component to DOM like this.

import React, { Component } from 'react';
    ... import bunch of components

class App extends Component { ... }

const formContainer = document.querySelector('#formContainer');
ReactDOM.render(App, formContainer);

Unfortunately, when I open website, I get error Uncaught SyntaxError: Unexpected identifier at import React, { Component } from 'react'; from preprocessed root React component file.
If I delete React from import statement (directly in preprocessed file), I get error Uncaught SyntaxError: Unexpected token {
and If I delete the first import line, I get the same Unexpected identifier error at next import line.
So, I think web browser have a problem with import statement.
I thought babel should take care of converting everything in JSX files to JS files that are able to run on web browser.

I'm sure that my JSX files are correct because I wrote these components in Create React App project before I copied all of JSX files to django project.
So, what should I do to add a React component to my website?

witoong623
  • 1,179
  • 1
  • 15
  • 32

1 Answers1

9

I've had to deal with this exact problem. I just needed to add a react component to a page and nothing else. Most tutorials online recommend decoupling React and Django, which wasn't feasible for the project I was working on. An easier way seems to involve creating a new app to contain the react components and adding this to the INSTALLED_APPS in your project's settings.py so the static files generated by webpack are discovered by django.

Setup yarn or npm and install a few dependencies and dev-depedencies that are required for transpiling the code. You can use your bundler of choice, I'm using webpack since it's the most popular:

cd react_component (or wherever your new project is)
yarn init -y
yarn add -D @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-cli
yarn add react react-dom

Create a webpack.config.js in your app directory with the following contents:

const path = require('path');

module.exports = {
  entry: path.resolve(__dirname, 'static_src', 'index.js'),
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
    ],
  },
  output: {  
    path: path.resolve(__dirname, 'static', 'react_component'),
    filename: 'bundle.js',
  },
  resolve: {
    extensions: ['*', '.js', '.jsx'],
  },
};

And a .babelrc in the same directory:

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

Create a static_src directory to store your JavaScript files, and a static directory for the bundled files webpack generates.

Create static_src/index.js and render your root component:

import React from 'react';  
import ReactDOM from 'react-dom';  
import Component from "./Component";  
  
ReactDOM.render(<Component/>, document.getElementById('component-root'));

and you should be good to go. Run npx webpack in the react_component/ directory to transpile your files and generate a bundle.js which you can include anywhere in your project like so:

{% load static %}
<div id="component-root"></div>
<script src="{% static 'react_component/bundle.js' %}"></script>
hrishi045
  • 91
  • 1
  • 3