Internet Bandaid   [RSS Feed]

Archive for May 21st, 2016

Reactive Programming with ReactJS

without comments

I’m just appreciating the concept of Reactive Programming right now.  And I’m seeing how ReactJS has made it easy.  From what I understand, the notion of reactive programming is that if you change the state of “something”, anything else that depends on it should also automatically (or reactively) update itself.  A simple example can be with Excel spreadsheets.  If in cell C1, you have the formula =B1+A1, any time you make a change in B1 or A1, C1 will automatically (aka reactively) update.  You do not have to manually go into C1 and re-calculate the value.
With ReactJS in javascript, they’ve made it much easier to do reactive programming.  Consider the simple code below as an example.
<html>
<head>
<script type=”text/javascript”>
var arrVals = ['First Row','Second Row','Third Row'];
$(document).ready(function(){
// populate template with content
for(let x=0; x<arrVals.length; x++)
{
addItem(arrVals[x]);
}
$(‘button’).click(function(){
addItem($(‘input’).val());
});
});
function addItem(text)
{
let item = document.createElement(‘li’);
li.innerHTML = text;
$(‘ul’).append(li);
}
</script>
</head>
<body>
<div id=”container”>
<input type=”text” value=”" />
<button type=”button”>Add Row</button>
<ul></ul>
</div>
</body>
</html>
This code should be pretty straightforward right?  When the page first loads, you’ll get a text field, a button and a list with items First Row, Second Row and Third Row.  If you press the Add Row button, it will take the text in your text field and add a new row to the ul.  The process by which the UL renders new LI after Add Row is pressed isn’t particularly reactive.  I say this because every time you press Add Row, a developer/custom defined function called addItem() needs to fire in order to create the new list.  This might seem trivial in our example.  But if you have a more sophisticated html mark up to define a much more complex user interface, always defining new html elements on the fly can be a very labourious and tedious effort that makes it very difficult to test.
A relatively more reactive approach would be after you press Add Row button, the text value from the text fields get stored in a state (eg. in an array as a property of a class).  Just saving that value to the state should automatically render a new interface without you needing to do anything.
ReactJS has an approach to handle just that.  Below is ReactJS code that achieves the same objectives as the javascript code above:
<html>
<head>
<script type=”text/javascript”>
class default MyProject extends React.Component {
getInitialState ()
{
return {arrNewVal:[]};
}
addRow()
{
let state = this.state;
state['arrNewVal'].push($(‘input’).val());
this.setState(state);
}
render() {
return (
<div>
<input type=”text” defaultValue=”" />
<button type=”button” onClick={this.addRow.bind(this)}>Add Row</button>
<ul>
{this.props.arrVal.map(function(item){
return <li>{item}</li>
})}
{this.state.arrNewVal.map(function(item){
return <li>{item}</li>
})}
</ul>
</div>
);
}
}
ReactDOM.render(<MyProject arrVal={['First Row','Second Row','Third Row']} />,$(‘#container’)[0]);
</script>
</head>
<body>
<div id=”container”></div>
</body>
</html>
What’s happening here is that I defined a react class called MyProject.  All react objects including MyProject has a render() function which outputs a user interface.  The line
ReactDOM.render(<MyProject arrVal={['First Row','Second Row','Third Row']} />,$(‘#container’)[0]);
Outputs the output of MyProject.render() into the #container div.   I’ve also passed in the initial 3 rows of content as an array into MyProject.
So here’s the secret sauce — any time you fire the this.setState() function (which populates this.state), and if this.state has changed some values, the React object will automatically fire MyProject.render().
This makes it much easier to maintain and update user interfaces when content has changed.  I don’t have to waste time writing a whole bunch of code to maintain / render my user interfaces every time the data/content has changed.   I can just rely on my render() function to re-fire any time I’ve updated data.

Written by John Lai

May 21st, 2016 at 4:23 pm

Posted in Uncategorized