Skip to content

Instantly share code, notes, and snippets.

@christiannwamba
Last active April 26, 2016 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christiannwamba/88b24f3f6a8cc04613d45f461e510217 to your computer and use it in GitHub Desktop.
Save christiannwamba/88b24f3f6a8cc04613d45f461e510217 to your computer and use it in GitHub Desktop.
Learning React
<h2>Introduction</h2>
<p>Today we are going to kick off the first installment in a new series of tutorials, <strong>Learning React</strong>, that will focus on becoming proficient and effective with Facebook's React library. Before we start building anything meaningful, its important that we cover some base concepts first, so lets get this party started.</p>
<h3>What is React?</h3>
<p>React is a UI library developed at Facebook to facilitate the creation of interactive, stateful &amp; reusable UI components. It is used at Facebook in production, and Instagram.com is written entirely in React.</p>
<p>One of it's unique selling points is that not only does it perform on the client side, but it can also be rendered server side, and they can work together inter-operably.</p>
<p>It also uses a concept called the Virtual DOM that selectively renders subtrees of nodes based upon state changes. It does the least amount of DOM manipulation possible in order to keep your components up to date.</p>
<h3>How does the Virtual DOM work?</h3>
<p>Imagine you had an object that you modeled around a person. It had every relevant property a person could possibly have, and mirrored the persons current state. This is basically what React does with the DOM.</p>
<p>Now think about if you took that object and made some changes. Added a mustache, some sweet biceps and Steve Buscemi eyes. In React-land, when we apply these changes, two things take place. First, React runs a "diffing" algorithm, which identifies what has changed. The second step is reconciliation, where it updates the DOM with the results of diff.</p>
<p>The way React works, rather than taking the real person and rebuilding them from the ground up, it would only change the face and the arms. This means that if you had text in an input and a render took place, as long as the input's parent node wasn't scheduled for reconciliation, the text would stay undisturbed.</p>
<p>Because React is using a fake DOM and not a real one, it also opens up a fun new possibility. We can render that fake DOM on the server, and boom, server side React views. </p>
<h2>Getting Started</h2>
<p>Getting started with React is as simple as downloading their provided starter kit:</p>
<p><a href="https://facebook.github.io/react/downloads/react-15.0.1.zip">React Starter Kit</a></p>
<p>You can also fork a JSFiddle they have provided:</p>
<p><a href="https://jsfiddle.net/reactjs/69z2wepo/">React JSFiddle</a></p>
<h3>Page Setup</h3>
<p>When setting up your page, you want to include <code>react.js</code>, <code>react-dom.js</code> and <code>JSXTransformer.js</code>, and then write your component in a script node with <code>type</code> set to <code>text/jsx</code>:</p>
<pre><code class="language-markup">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;script src="build/react.js"&gt;&lt;/script&gt;
&lt;script src="build/react-dom.js"&gt;&lt;/script&gt;
&lt;script src="build/JSXTransformer.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="mount-point"&gt;&lt;/div&gt;
&lt;script type="text/jsx"&gt;
// React Code Goes Here
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>React DOM is supporting library and was introduced in recent version of React. The React DOM implementation was initially in the React library but become a stand alone library in v0.14</p>
<p>In React, components mount to an element, so in this example we can use the div <code>mount-point</code> as it's parent container.</p>
<p>While this is the easiest way to get started, when its time to actually build something, its probably a good idea to use Browserify or webpack and set your components up in separate files.</p>
<h2>The Basics</h2>
<p>React's basic building blocks are called components. Lets write one:</p>
<pre><code class="language-javascript">
&lt;script type="text/jsx"&gt;
/** @jsx React.DOM */
ReactDOM.render(
&lt;h1&gt;Hello, world!&lt;/h1&gt;,
document.getElementById('myDiv')
);
&lt;/script&gt;
</code></pre>
<p>If you haven't seen one of these before, you are probably wondering what Javascript/HTML chimera sorcery is taking place right now. </p>
<h3>JSX</h3>
<p>It's called JSX, and it is a Javascript XML syntax transform. This lets you write HTML-<em>ish</em> tags in your Javascript. I say HTML-<em>ish</em> because there are a couple gotchas. You are really just writing XML based object representations.</p>
<p>For regular html tags, the <code>class</code> attribute is <code>className</code> and the <code>for</code> attribute is <code>htmlFor</code> in JSX because these are reserved words in Javascript. More differences can be <a href="http://facebook.github.io/react/docs/jsx-gotchas.html">reviewed here</a>.</p>
<p>Now you don't need to use JSX, here is what the syntax looks like without it:</p>
<pre><code class="language-javascript">
/** @jsx React.DOM */
React.render(
React.createElement('h1', null, 'Hello!'),
document.getElementById('myDiv')
);
</code></pre>
<p>You can read more about element support <a href="http://facebook.github.io/react/docs/tags-and-attributes.html">here</a> if you'd like.</p>
<h3>Components</h3>
<p>When using the ReactDOM's <code>render</code> method above, our first argument is the component we want to render, and the second is the DOM node it should mount to. We can use the <code>createClass</code> method to create custom component classes. It takes an object of specifications as it's argument. Lets create one below:</p>
<pre><code class="language-javascript">
var MyComponent = React.createClass({
render: function(){
return (
&lt;h1&gt;Hello, world!&lt;/h1&gt;
);
}
});
</code></pre>
<p>After creating a class we can render it to our document like so:</p>
<pre><code class="language-javascript">
ReactDOM.render(
&lt;MyComponent/&gt;,
document.getElementById('myDiv')
);
</code></pre>
<p>Cool, huh? </p>
<h3>Props</h3>
<p>When we use our defined components, we can add attributes called props. These attributes are available in our component as <code>this.props</code> and can be used in our render method to render dynamic data:</p>
<pre><code class="language-javascript">
var MyComponent = React.createClass({
render: function(){
return (
&lt;h1&gt;Hello, {this.props.name}!&lt;/h1&gt;
);
}
});
ReactDOM.render(&lt;MyComponent name="Handsome" /&gt;, document.getElementById('myDiv'));
</code></pre>
<h2>Specs, Lifecycle &amp; State</h2>
<p>The <code>render</code> method is the only required spec for creating a component, but there are several lifecycle methods &amp; specs we can use that are mighty helpful when you actually want your component to do anything.</p>
<h3>Lifecycle Methods</h3>
<ul>
<li><strong>componentWillMount</strong> - Invoked once, on both client &amp; server before rendering occurs.</li>
<li><strong>componentDidMount</strong> - Invoked once, only on the client, after rendering occurs.</li>
<li><strong>shouldComponentUpdate</strong> - Return value determines whether component should update.</li>
<li><strong>componentWillUnmount</strong> - Invoked prior to unmounting component.</li>
</ul>
<h3>Specs</h3>
<ul>
<li><strong>getInitialState</strong> - Return value is the initial value for state.</li>
<li><strong>getDefaultProps</strong> - Sets fallback props values if props aren't supplied.</li>
<li><strong>mixins</strong> - An array of objects, used to extend the current component's functionality.</li>
</ul>
<p>There are several more specs &amp; lifecycle methods that you can read about <a href="http://facebook.github.io/react/docs/component-specs.html">here</a>.</p>
<h3>State</h3>
<p>Every component has a <code>state</code> object and a <code>props</code> object. State is set using the <code>setState</code> method. Calling <code>setState</code> triggers UI updates and is the bread and butter of React's interactivity. If we want to set an initial state before any interaction occurs we can use the <code>getInitialState</code> method. Below, see how we can set our component's state:</p>
<pre><code class="language-javascript">
var MyComponent = React.createClass({
getInitialState: function(){
return {
count: 5
}
},
render: function(){
return (
&lt;h1&gt;{this.state.count}&lt;/h1&gt;
)
}
});
</code></pre>
<p> </p>
<h2>Events</h2>
<p>React also has a built in cross browser events system. The events are attached as properties of components and can trigger methods. Lets make our count increment below using events:</p>
<pre><code class="language-javascript">
/** @jsx React.DOM */
var Counter = React.createClass({
incrementCount: function(){
this.setState({
count: this.state.count + 1
});
},
getInitialState: function(){
return {
count: 0
}
},
render: function(){
return (
&lt;div class="my-component"&gt;
&lt;h1&gt;Count: {this.state.count}&lt;/h1&gt;
&lt;button type="button" onClick={this.incrementCount}&gt;Increment&lt;/button&gt;
&lt;/div&gt;
);
}
});
ReactDOM.render(&lt;Counter/&gt;, document.getElementById('mount-point'));
</code></pre>
<p data-height="310" data-theme-id="2089" data-slug-hash="kxrDu" data-default-tab="result" data-user="kenwheeler" class='codepen'>
See the Pen <a href='http://codepen.io/kenwheeler/pen/kxrDu/'>kxrDu</a> by Ken Wheeler (<a href='http://codepen.io/kenwheeler'>@kenwheeler</a>) on <a href='http://codepen.io'>CodePen</a>.
</p>
<p> </p>
<h2>Unidirectional Data Flow</h2>
<p>In React, application data flows unidirectionally via the <code>state</code> and <code>props</code> objects, as opposed to the two-way binding of libraries like Angular. This means that, in a multi component heirachy, a common parent component should manage the state and pass it down the chain via props.</p>
<p>Your state should be updated using the <code>setState</code> method to ensure that a UI refresh will occur, if necessary. The resulting values should be passed down to child components using attributes that are accessible in said children via <code>this.props</code>.</p>
<p>See this example that shows this concept in practice:</p>
<pre><code class="language-javascript">
/** @jsx React.DOM */
var FilteredList = React.createClass({
filterList: function(event){
var updatedList = this.state.initialItems;
updatedList = updatedList.filter(function(item){
return item.toLowerCase().search(
event.target.value.toLowerCase()) !== -1;
});
this.setState({items: updatedList});
},
getInitialState: function(){
return {
initialItems: [
"Apples",
"Broccoli",
"Chicken",
"Duck",
"Eggs",
"Fish",
"Granola",
"Hash Browns"
],
items: []
}
},
componentWillMount: function(){
this.setState({items: this.state.initialItems})
},
render: function(){
return (
&lt;div className="filter-list"&gt;
&lt;input type="text" placeholder="Search" onChange={this.filterList}/&gt;
&lt;List items={this.state.items}/&gt;
&lt;/div&gt;
);
}
});
var List = React.createClass({
render: function(){
return (
&lt;ul&gt;
{
this.props.items.map(function(item) {
return &lt;li key={item}&gt;{item}&lt;/li&gt;
})
}
&lt;/ul&gt;
)
}
});
ReactDOM.render(&lt;FilteredList/&gt;, document.getElementById('mount-point'));
</code></pre>
<p data-height="475" data-theme-id="2089" data-slug-hash="jDKEo" data-default-tab="result" data-user="kenwheeler" class='codepen'>
See the Pen <a href='http://codepen.io/kenwheeler/pen/jDKEo/'>jDKEo</a> by Ken Wheeler (<a href='http://codepen.io/kenwheeler'>@kenwheeler</a>) on <a href='http://codepen.io'>CodePen</a>.
</p>
<h2>Conclusion</h2>
<p>Now that we have reviewed some React basics, take some time to check out the <a href="http://facebook.github.io/react/docs/top-level-api.html">React API</a> and read up a bit on <a href="http://facebook.github.io/react/docs/jsx-in-depth.html">JSX</a>.</p>
<p>In the next installment of <strong>Learning React</strong> we will be integrating with Express to build an app that renders on the server side, as well as the client side, and uses socket.io to keep the two in sync.</p>
<p>Stay tuned!</p>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment