By Andrew Allbright
Introduction
If you’ve done anything in the JavaScript UI world, you most certainly have heard of React.JS by Facebook. If not, you might be asking, “What is React.JS?” It has a very high adoption rate, with big names like Netflix, Yahoo, and Facebook, among many, many others using it for Web sites, mobile applications, and even for VR applications. But what is this framework that has so many companies excited to adopt it? In this article. I will show you the basics of the framework and, through examples, unveil the mystery behind React.JS.
Taxonomy
First things first, though; we should establish where React fits with other JavaScript frameworks. Fortunately, this is quite simple because React.JS is simply a library concerned with components utilizing the expressiveness of JavaScript intermixed with an HTML-like template syntax. If you consider a typical Web application through the prism of the Model View Controller, React is simply giving you the “V” of “MVC.” You may read that and think “oh, so it’s a template engine like HandleBars or Jade then?” No, this is more than your typical template engine library due to how much it leverages JavaScript to get things done.
With that out of the way, let’s dive deeper into React.JS and get to some code.
React Is Simple
There is only one required method you must define when you create a new React.JS component. This is the render function and it can either return JSX or JavaScript.
Assuming you define an HTML document, as such…
html <html> <head> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/ bootstrap/3.3.6/css/bootstrap.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/ 15.0.1/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/ 15.0.1/react-dom.min.js"></script> </head> <body> <div id="app"></div> </body> </html>
Please do notice that there are two React.JS libraries included in the document: react.min.js and react-dom.min.js. react is responsible for defining your components, but react-dom is responsible for putting your component(s) on the page. I’ve thrown in bootstrap just to make the document look prettier. Now, here is a very simple component definition along with the instantiation-defined component to the HTML document.
javascript const App = React.createClass({ render: function () { return ( <div className='container'> <h1> Hello, React! </h1> </div> ); } }); ReactDOM.render(<App />, document.findElementById('app'));
That’s all that’s required. React.createClass is used to define your component. It’s the render function that returns a simple JSX statement, which looks very similar to HTML. The component definition is stored inside a variable, App (using ES6’s new keyword const), and then ReactDOM.render is used to place the component <App /> (this is JSX, by the way) inside <div id="app"></div>.
JSX is a key element in React components, so let’s discuss it.
JSX
React.JS uses JavaScript to create components through JSX. JSX is a language that looks like HTML, but ultimately compiles down to JavaScript statements. JSX is syntactic sugar to make creating HTML components easier to work with. Truthfully, there are only minor differences between HTML and JSX, but that is a topic beyond the scope of this article.
Here is an example of JSX:
javascript const App = React.createClass({ render: function () { return ( <div> This is JSX syntax! </div> ); } });
That <div> This is JSX syntax! </div> is the JSX portion and will compile down to React.createElement("div", null, " This is JSX syntax! "). To rewrite the previous snippet with the JSX compiled to JavaScript statements, the preceding would look like this:
javascript const App = React.createClass({ render: function () { return React.createElement( "div", null, " This is JSX syntax! " ); } });
Although knowing what exactly JSX will compile down to at any given time is not important when working with React.JS, it’s worthwhile to understand what’s going on under the covers.
Exposed DOM Lifecyle Methods
By reading React.JS’s Component Specs documentation, you will see that React exposes DOM-related events to bind callbacks to. These are related to component instance variables, and the life cycle of when your React.JS component will bind to the document.
To better illustrate these methods, consider the following code:
javascript const App = React.createClass({ getInitialState: function () { // Private component instance object to // attach variables to return {}; }, getDefaultProps: function () { /* Default component object that will be overridden by any properties passed in */ return {}; }, componentWillMount: function () { /* Callback that will be executed before component is added to DOM. This is a great place for component- specific setTimeout or AJAX requests to occur. */ }, componentDidMount: function () { /* Callback that will be executed immediately after component is added to DOM. Great place to instantiate any jQuery components. */ }, componentWillReceiveProps: function (nextProps) { /* Callback executed when new properties are executed. You typically won't need this. */ }, shouldComponentUpdate: function (nextProps, nextState) { // If you never want to rerun DOM, return 'false' }, componentWillUpdate: function (nextProps, nextState) { // Callback executed before updating DOM }, componentDidUpdate: function (prevProps, prevState) { // Callback executed after updating DOM }, componentWillUnmount: function () { /* Callback executed before removing component from DOM. This is a great spot to clean up anything relating to this component outside React's "ecosystem," perhaps a lingering AJAX poller attached to window.setInterval? */ }, render: function () { return ( <div> Component Template Output </div> ); } });
There are many lifecycle methods exposed to allow you to create complicated components. By leveraging these lifecycle methods, you can encapsulate any libraries you want to use in your application. You can combine use of these methods with the expressiveness of JavaScript to create very powerful yet modular UI predictably.
Expressiveness of JavaScript
React.JS allows you to use the expressiveness of JavaScript to create complex components. This is the “secret sauce” that really sets React.JS apart from other template engines. Within templates, you can “exit” JSX to write JavaScript expressions using curly braces ({ /* JS expression */ }). Consider if you waanted to use a variable within JSX.
javascript const App = React.createClass({ render: function () { const headerText = 'Custom string value'; return ( <h1> {headerText} </h1> ); } });
This would output <h1> Custom string value </h1>.
You can use JavaScript ternary operations to render one thing or another based on a condition.
javascript const App = React.createClass({ render: function () { // randomly assign to true or false const logicGate = Math.random() > 0.5; return ( <div> { logicGate ? <p> This is displayed given the logic gate is true </p> : <p> This is displayed given the logic gate is false </p> } </div> ) } });
By utilizing the expressiveness of JavaScript, you even can iterate over collections to produce complex templates with ease.
javascript const App = React.createClass({ render: function () { const collection = [ 'we', 'require', 'additional', 'pylons' ]; return ( <ul> {collection.map((text) => { return (<li> {text} </li>); })} </ul> ); } });
Props and State
Every component’s render function has access to two objects: props and state. Both props and state are simply JavaScript objects that have properties that you can then apply logic to while you render. I will now go over what unique attributes define both and how you would want to use them in your React.JS components. One thing in common with both state and props is whenever either objects change, React will execute render and update DOM if required.
Props
Props are strings, floats, objects, or other React components you pass into a component that then will be namespaced onto the this.props object. It’s a way of manipulating the output of a component “from the outside.” If no properties are passed in, this.props will be undefined. However, if you pass in properties onto the component or return an object from getDefaultProps, you will have access to object properties. It’s best practice to define a default property whenever you create a component that expects them to be passed in. To illustrate this concept, consider this component.
javascript const App = React.createClass({ getDefaultProps: function () { return { title: undefined } }, render: function () { const title = this.props.title return ( <h1> { title ? {title} : null} </h1> ); } }); ReactDOM.render( <App title='Property example'/>, document.findElementById('app') );
Because title='this.props example' is attached as an attribute to <App />, this.props.title will equal 'this.props example' inside render, overriding the default value of undefined we set in getDefaultProps. Had I not attached that property, this.props.title would have remained undefined and null would have been returned inside the JSX template.
Had the attribute changed to title='Some other title' at some point, the React component would have re-rendered to reflect the new attribute value.
State
state operates akin to props; however, this is meant to manipulate the component from the inside rather than the outside. There is an extra method exposed to React.JS components to update state invoked through this.setState to update the state object, thus triggering a render and DOM update (if necessary).
javascript const App = React.createClass({ componentDidMount: function () { let timeout = window.setTimeout(() => { this.setState({ delayedVariable: 'After 5 seconds this text will appear' }); window.clearTimeout(timeout); }, 5000); }, render: function () { const delayedVariable = this.state.delayedVariable; return ( <div> <h3> Timeout Example </h3> {delayedVariable ? <p> {delayedVariable} </p> : null} </div> ); } });
Next Steps
I’ve only touched on the basics of React.JS. However, now that you’ve seen code samples, I hope you have a better sense of what this library can do. React.JS is a very simple framework that a developer can grasp but once you embrace what sets it apart—JavaScript—you will constantly be thinking of clever ways to express your UI in very simple, modular terms.