Skip to content

An example app made with Create React App which introduces a Reason component

Notifications You must be signed in to change notification settings

eanplatter/introduce-reason-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Introducing Reason to an existing React Project

One of the hardest things about trying out new tools is that they don't always play well with your existing code, or if they do it takes a lot of time and effort to make it happen.

Reason happens to be extremely easy to integrate into an existing React app with the help of reason-react

In this README I am going to attempt to convey how I added Reason to an existing app created by create-react-app. The code in this project is an "existing codebase" with Reason implemented.

Step 1 - BuckleScript Config

BuckleScript is "a backend for the OCaml compiler which emits JavaScript". It is what turns our Reason code into JavaScript we can import into our React code.

We will run BuckleScript in our terminal, it will read our code and turn it into JavaScript. In order to point it in the right direction we will need to create a bsconfig.json file. This is similar to webpack.config.js or .babelrc files. It merely configures BuckleScript.

In the root of your project create a file named bsconfig.json.

I borrowed most of this bsconfig.json file from Cheng Lou's reason-react-example

bsconfig.json

  {
    "name" : "introduce-reason",
    "reason" : { "react-jsx" : true },
    "bs-dependencies": ["reason-react", "reason-js"],
    "sources": [
      {
        "dir": "src",
      }
    ],
  }

Step 2 - Add Dependencies

We need 3 new dependencies in order to make this work: reason-react, reason-js, and bs-platform.

To install these, run the following in your terminal:

npm i -S reason-js reason-react && npm i -D bs-platform

Step 3 - Add a BuckleScript NPM Script

We are going to need a way to run BuckleScript over our codebase. Since we've installed the bs-platform dependency and have created our bsconfig.json file we are set to start running BuckleScript! Add a script to our package.json file which runs BuckleScript, it should look something like this:

  "scripts": {
    "buckle:up": "bsb -make-world -w",
    "buckle:clean": "bsb -clean-world",
    "start": "react-scripts start",
  }

The names are arbitrary, I decided to call my scripts buckle:up and buckle:clean. So now in my terminal I can run it:

npm run buckle:up

Once we do this, if everything worked properly we should see a new directory in the root of our app named lib/; this is where BuckleScript will put our transpiled Reason components.

If we look in the lib/ directory right now we will see that there is a bs/ directoy. This isn't really important for us to look at right now, once we have a Reason component we will also see a js/ directory. This js/ directory is where BuckleScript is going to put our component! Let's go ahead and get started on that.

Step 4 - Writing a Reason Component

In the /src directory of our project let's create a new file called Intro.re. This is going to be a React Reason component which is going to replace the into paragraph on the default create-react-app main page.

Intro.re

module Intro = {
  include ReactRe.Component.JsProps;
  type props = { message: string };
  let name = "Intro";
  let render { props } => <p className="App-intro"> (ReactRe.stringToElement props.message) </p>;
  type jsProps = Js.t {. message : string };
  let jsPropsToReasonProps =
    Some (
      fun jsProps => { message: jsProps##message }
    );
};

include ReactRe.CreateComponent Intro;

let createElement ::message => wrapProps { message };

I don't want to dive too deep into the Reason syntax here, but essentially this is a component which takes in a message props and puts it into a <p /> tag with the className "App-intro".

Step 5 - Tieing it All Together

In order to do this, I had 2 terminal windows open, one running Webpack, the other running BuckleScript. Make sure both of these are running:

Running Webpack

npm start

Running BuckleScript

npm run buckle:up

Once these are running we should be able to see that our component has been transpiled by BuckleScript to lib/js/src/intro.js and it should look something like this:

// Generated by BUCKLESCRIPT VERSION 1.6.0+dev, PLEASE EDIT WITH CARE
'use strict';

var Curry   = require("bs-platform/lib/js/curry");
var React   = require("react");
var ReactRe = require("reason-react/lib/js/src/reactRe");

var include = ReactRe.Component[/* JsProps */9];

var componentDidMount = include[0];

var componentWillUpdate = include[1];

var componentDidUpdate = include[2];

var componentWillReceiveProps = include[3];

var componentWillUnmount = include[4];

var getInstanceVars = include[5];

var getInitialState = include[6];

var name = "Intro";

function render(param) {
  return React.createElement("p", {
              className: "App-intro"
            }, param[/* props */1][/* message */0]);
}

var jsPropsToReasonProps = /* Some */[function (jsProps) {
    return /* record */[/* message */jsProps.message];
  }];

var Intro = /* module */[
  /* componentDidMount */componentDidMount,
  /* componentWillUpdate */componentWillUpdate,
  /* componentDidUpdate */componentDidUpdate,
  /* componentWillReceiveProps */componentWillReceiveProps,
  /* componentWillUnmount */componentWillUnmount,
  /* getInstanceVars */getInstanceVars,
  /* getInitialState */getInitialState,
  /* name */name,
  /* render */render,
  /* jsPropsToReasonProps */jsPropsToReasonProps
];

var include$1 = ReactRe.CreateComponent([
      name,
      getInstanceVars,
      getInitialState,
      componentDidMount,
      componentWillReceiveProps,
      componentWillUpdate,
      componentDidUpdate,
      componentWillUnmount,
      jsPropsToReasonProps,
      render
    ]);

var wrapProps = include$1[1];

var createElement = Curry.__1(wrapProps);

var comp = include$1[0];

exports.Intro         = Intro;
exports.comp          = comp;
exports.wrapProps     = wrapProps;
exports.createElement = createElement;
/* include Not a pure module */

If that is all working then we should be able to now import our Reason component into our existing React app. I am going to import it into App.js as Intro: App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import Intro from '../lib/js/src/intro'
import './App.css';

...and replace the paragraph with the className "App-intro" with:

<Intro.comp message="To get started, edit src/App.js and save to reload." />

All done!

That should be it! If you've made it this far then congratulations you've successfully introduced Reason into a React codebase! If you experienced any issues with this walkthrough please open an issue or if there are changes you think we should make feel free to open a PR.

A big thanks to Cheng Lou and his reason-react-example which served as my primary source of information while doing this. Be sure to check out his example project for a more in depth look at using reason-react.

About

An example app made with Create React App which introduces a Reason component

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published