How to use React.js with AdonisJs

Viewed 5381

How can I use React.js in the front-end of my AdonisJs project?
I've tried to install react with npm install react I thought this will works correctly. I made a file app.js with this code:

var React = require('react');
var ReactDOM = require('react-dom');

export default class Index extends Component {
  render() {
    return (< h1 > hello world! < /h1>)
  }
}
ReactDOM.render( < Index / > , document.getElementById('example'))

But this isn't working at all, I don't know what to do more I have searched about how to use React in Adonis but I didn't find anything interesting.

3 Answers

I strongly suggest you to use WebPack for this task.

create a webpack.config.js file in your root directory: maybe your code need some changes but this is the idea:

const webpack = require('webpack');
   var CopyWebpackPlugin = require('copy-webpack-plugin');
   var HtmlWebpackPlugin = require('html-webpack-plugin');
   var ExtractTextPlugin = require('extract-text-webpack-plugin');
   var path = require('path');
   var pkgBower = require('./package.json');

module.exports = {
  target: "web",
  devtool: "source-map",
  node: {
    fs: "empty"
  },
  entry: {
      'app': path.join(__dirname, 'react-app', 'Index.jsx')
  },
  resolve: {
    modules: [__dirname, 'node_modules', 'bower_components'],
    extensions: ['*','.js','.jsx', '.es6.js']
  },
  output: {
    path: path.join(__dirname, 'public', 'src'),
    filename: '[name].js'
  },
  resolveLoader: {
     moduleExtensions: ["-loader"]
  },
  module: {
    loaders: [
      {
          test: /jquery\.flot\.resize\.js$/,
          loader: 'imports?this=>window'
      },
      {
          test: /\.jsx?$/,
          exclude: /(node_modules|bower_components)/,
          loader: 'babel-loader',
          query: {
              presets: ['es2015', 'react', 'stage-0'],
              compact: false
          }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      },
      {
          test: /\.woff|\.woff2|\.svg|.eot|\.ttf/,
          loader: 'url?prefix=font/&limit=10000'
      },
      {
          test: /\.(png|jpg|gif)$/,
          loader: 'url?limit=10000'
      },
      {
          test: /\.scss$/,
          loader: 'style!css!sass?outputStyle=expanded'
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    }),
    new CopyWebpackPlugin([{
        from: 'img',
        to: 'img',
        context: path.join(__dirname, 'react-app')
    }, {
        from: 'server',
        to: 'server',
        context: path.join(__dirname, 'react-app')
    }, {
        from: 'fonts',
        to: 'fonts',
        context: path.join(__dirname, 'react-app')
    }]),
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery'
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: { warnings: false },
      mangle: true,
      sourcemap: false,
      beautify: false,
      dead_code: true
    }),

    new webpack.ContextReplacementPlugin(/\.\/locale$/, 'empty-module', false, /js$/)
  ]
};

Then put your app in your root directory, in a folder react-app/ and your components can go inside that folder:

For example your file: [Index.jsx]

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

class Index extends Component {
  render() {
    return (< h1 > hello world! < /h1>)
  }
}

ReactDOM.render( < Index / > , document.getElementById('example'));

you don't need to export this Index component in this case, but in case you need to just use export default ComponentName at the end of your component file.

The next step is in your routes file (I'm using AdonisJS 4) but is very similar for the version 3.x

Route.any("*", ({ view, response }) => (
   view.render('index')
))

Then your index (.njk, or .edge) file (under resources/views) should look something like this:

<html>
   <head>
     <link rel="stylesheet" href="/src/styles.css">
      <script type="text/javascript" src="/src/app.js"></script>
   </head>

   <body>
      <div id="example"></div>
   </body>
</html>

-- You need to install some npm/ packages with npm or yarn, and remember to run in another terminal window or tab,

 webpack -d --watch --progress

Regards.

Related