3

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.

Nope
  • 22,147
  • 7
  • 47
  • 72
Ayech Hamza
  • 159
  • 2
  • 10
  • You have no errors in the console? and `return (< h1 > hello world! < /h1>)` or `ReactDOM.render( < Index / >...` are not giving you any issues at all? – Nope Nov 28 '17 at 09:30
  • SyntaxError: expected expression, got ')' in this line return (< h1 > hello world! < /h1>) – Ayech Hamza Nov 28 '17 at 09:31
  • There you go. Fix those syntax errors and you are good to go. I assume they need to be strings... Also in the case of `ReactDOM.render(...)` have a look at their [**Documentation**](https://reactjs.org/docs/react-dom.html#render) for the usage. – Nope Nov 28 '17 at 09:32
  • thanks dude, but how can i import react? console tells me that : ReferenceError: require is not defined, also i can''t run npm run dev or watch – Ayech Hamza Nov 28 '17 at 09:37

3 Answers3

3

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.

Juan Ricardo
  • 143
  • 8
0

This works. You are missing React.Component.

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

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

Alternatively you can use import React, {Component} from 'react'; if you want to use your code structure.

Kunukn
  • 2,136
  • 16
  • 16
0

For decoupled use, just build your React app and copy the build to Adonis public folder.

Marco Afonso
  • 316
  • 2
  • 11