In the finished application the real-world electronic sensors update the React component’s state as soon as they receive new readings. Then in the render function the LED component, using the newly updated state, works out whether it needs to switch on or off.

This is the second article in a series about Standardising IoT projects. In the first part I tried to apply the principle of separation of concerns from web development to IoT projects by inventing a new XML based markup language.

In the second part we take a completely different approach and use React.

My goal was to be able to use React’s most powerful features to organise hardware projects: components, state, props and lifecycle methods.

<Led /> <LightSensor /> <MoistureSensor />

If you wish to browse the finished source code, have a look at the project on Github:

https://github.com/webondevices/react-iot

React without React DOM

The great thing about React is that it doesn’t have to be used with the DOM which is why React DOM has been extracted from React in version 0.14. Here’s the note from the official change log:

“As we look at packages like react-native, react-art, react-canvas, and react-three, it has become clear that the beauty and essence of React has nothing to do with browsers or the DOM.”

We now also have React VR so it’s clear that React is perfectly suitable to be used without the DOM.

Running React on the server

The react-server tool was designed for server-side rendering of React apps but unfortunately all it does is runs through the component hierarchy and spits out a string version of the resulting HTML markup which you can send back to the browser as a response.

This isn’t exactly what I wanted to achieve. Instead, I wanted the React app to keep live and running in Node.js: watch state changes, re-render if needed and trigger life-cycle methods.

The solution was to run the main React component through react-test-renderer which kept the app live and running:

const React = require(‘react’);

const ReactTestRenderer = require(‘react-test-renderer’);

const World = require(‘./components/World’); const rootElement = React.createElement(World, null, null);

const world = ReactTestRenderer.create(rootElement);

Defining Electronic Components

Right now React IoT components depend on Johnny-Five which is an I/O library communicating with the Arduino microcontroller board directly via the USB port.

Let’s look at the working example and what we have inside the <World/> parent component. The constructor of the World class is responsible for initialising the Arduino board:

const arduino = new five.Board();

arduino.on(‘ready’, () => this.setState({ready: true}));

In the render function the basic mechanic of the application becomes clear:

<Led pin={2} on={this.state.moisture > 500}/>

<Led pin={4} on={this.state.light < 130}/> <LightSensor pin={‘A1’} update={this._update}/>

<MoistureSensor pin={‘A2’} update={this._update}/>

All components have a pin property which will tell React IoT which physical Arduino pin the component is connected to. The LightSensor and the MoistureSensor components are both responsible for updating their own respective states: this.state.moisture and this.state.light .

Light and Temperature sensors

The Led components both have an on property which expects a boolean value. If you pass true the LED will switch on, if the evaluation is false it will switch off.

When the sensor readings change the states are updated immediately, which triggers a re-render, so the Led components can receive an up-to-date state to work out whether they need to switch on or off.

Behaviour of the Led component

In the constructor of the Led component a new instance of the Led object from Johnny-Five is initialised:

this._ledInstance = new five.Led(this.props.pin);

Then in the render function the on and off methods are triggered depending on the value of the passed in on property:

if (this.props.on) {

this._ledInstance.on();

} else {

this._ledInstance.off();

}

The sensor components

The light and the moisture sensors work very similarly. Again, a new Johnny-Five object instance is created in the constructor:

this._sensorInstance = new five.Sensor({

pin: this.props.pin,

freq: 1000

});

Then in the componentDidMount method an event listener is set up where the passed in update function is called each time the component receives new sensor data:

this._sensorInstance.on(‘data’, reading => {

this.props.update(‘light’, reading);

});

Feedback

Since this is only a proof of concept right now and everything is work-in-progress, I would appreciate some feedback. Let me know what you think or if you other ideas around improving this!