In this tutorial, we are going to refactor the bootstrap thumbnail component into React components. Here is a link the completed github repo. I would recommend doing the tutorial first and visiting this at the end if you have any problems.
Here is a basic picture of what we want our end result to be. We are going to make two thumbnails that show the type of tutorial, an image, and a button with a number of tutorials for that related subject. From the picture, can you guess how many React components there are?
First, you may want to install a React package for your text-editor before we get started. This will help with syntax highlighting when we start writing JSX files. Second, you can fork and clone this repository. I've created a new branch for each section as we move along the course if you get lost.
After you have cloned this repository, run:
$ npm i
React components are written in JSX. JSX gives you the ability to write HTML within javascript files. This is the life-blood of building React components, however, the JSX files need to be compiled into javascript. The easiest way to do this is with the gulp build process. This gulp file will not only compile from JSX to javascript, but will order the files properly and send all the code to a single file, main.js.
Run gulp from the console to start your compiler. Leave the gulp file running and it will automatically update with your main.js whenever changes are made.
The gulp file will also run a browser sync to that it will automatically update the browswer whenever we make changes.
To get started if we run the command:
$ gulp
We see the word "Hello!" So let's dive into the code and see where this comes from.
Normally, app.jsx is the the platform to launch your JSX files. For now, we will put all over our components and code into the app.jsx for simplicity. We will refactor each component into seperate files at the end as a stretch goal.
So, you'll notice the first thing in the app.jsx is to require in React. We need to add react so that we have access to all of its methods and functionality. The next thing we see is:
var Hello = React.createClass({
render: function() {
return <h1 className="red">
Hello!
</h1>
}
});
This is our first look at at React component. First, it is convention to give your components a capitalized variable name. Second, we'll set our new variable equal too the method 'createClass' called on React. 'createClass' has A LOT of built in methods to help build React components, however, the core function of 'createClass' is the 'render' function. The 'render' function is originally called twice, once when the DOM is opened and again when the DOM is fully loaded. It can be called additional times for when new data is passed into the component, however, that is beyond the scope of this tutorial. Inside, the render method we'll see some JSX. Here we see some standard HTML except for one thing, 'className'. 'className' acts as the exact same thing as 'class' in standard HTML, but is used for compiling purposes.
The next bit of code we see is:
// React, please render this class
var element = React.createElement(Hello, {});
Here, is where we are creating a React element. When we create the element we pass in the name of the component we want to create, and the data, if any, that we want to pass into the component.
Finally, we see the react render method. Here we are passing in the element we just created and the second parameter is where on the DOM we want to attach our new element. If you noticed we have an empty div in our index.html with the class of 'container' and that is where we want to attach our new element.
// React, after you render this class, please place it in my body tag
React.render(element, document.querySelector('.container'));
Now let's try making our own component. When looking at our thumbnails the first component we are going to make is the Badge. The badge will act as a button on our thumbnail that will have text and show the number of tutorials for that specific subject. So lets get to it...
First, lets get rid of the JSX inside the render function at in our app.jsx and change the name of the component from Hello to Badge. So the code should appear like this.
var React = require('react');
var Badge = React.createClass({
render: function() {
return
}
});
var element = React.createElement(Badge, {});
React.render(element, document.querySelector('.container'));
Next, lets add our code to the render function, using the bootstrap badge component as a template
var Badge = React.createClass({
render: function() {
return <button className="btn btn-primary" type="button">
See Tutorials <span className="badge">32</span>
</button>
}
});
Now we should have our badge button rendered on the DOM, but you have noticed, what if we want this button to be dynamic and not hard coded... Lets refactor the badge to take parameters and pass the data through here:
var element = React.createElement(Badge, {title: 'See Tutorials ', number: 32});
And our new badge component will look like:
var Badge = React.createClass({
render: function() {
return <button className="btn btn-primary" type="button">
{this.props.title}<span className="badge">{this.props.number}</span>
</button>
}
});
So here is we make this component dynamic:
- {this.props.title}
- {this.props.number}
- When writing JSX, we call React methods by wrapping them in {}
- React components use properties on their JSX elements to pass data through to each component. Components can then call that data using 'this.props'. We'll see more of this in our next component.
Now lets create a single thumbnail component using the bootstrap thumbnail html as our foundation.
var Thumbnail = React.createClass({
render: function() {
return <div class="col-sm-6 col-md-4">
<div class="thumbnail">
<img src="..." alt="...">
<div class="caption">
<h3>Thumbnail label</h3>
<p>...</p>
<p><a href="#" class="btn btn-primary" role="button">Button</a> <a href="#" class="btn btn-default" role="button">Button</a></p>
</div>
</div>
</div>
}
});
Similar to the Badge component, lets first go through and add our {this.props} to items we want to be dynamic.
var Thumbnail = React.createClass({
render: function() {
return <div className="col-sm-6 col-md-4">
<div className="thumbnail">
<img src={this.props.imageUrl} />
<div className="caption">
<h3>{this.props.header}</h3>
<p>{this.props.description}</p>
<p><a href="#" class="btn btn-primary" role="button">Button</a> <a href="#" class="btn btn-default" role="button">Button</a></p>
</div>
</div>
</div>
}
});
Now lets replace the button with our badge component that we just created. Be sure to analyze how the Badge component is added. How are we passing data through the Badge component?
var Thumbnail = React.createClass({
render: function() {
return <div className="col-sm-6 col-md-4">
<div className="thumbnail">
<img src={this.props.imageUrl} />
<div className="caption">
<h3>{this.props.header}</h3>
<p>{this.props.description}</p>
<p>
<Badge title={this.props.title} number={this.props.number}/>
</p>
</div>
</div>
</div>
}
});
Next let's create a global variable called options that we will pass into our create element function so we can pass in data into our component.
var options = {
title: 'See tutorials ',
number: 32,
header: 'Learn React',
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
imageUrl: 'http://formatjs.io/img/react.svg'
};
Finally, lets update our createElement method by passing in our Thumbnail component and the options variable we just made. And after our gulp file recompiles we should see a nice thumbNail with our badge component nested inside.
var element = React.createElement(Thumbnail, options);
Now, what if we wanted a list of thumbnails?
This final part will definitely be the most complicated component we have made thus far, but I will try to explain as best as possible, however, this will probably just take some time and repetition to fully understand what is happening. First though, lets update our options to incorporate data for our second thumbnail.
var options = {
thumbnailData: [
{
title: "See tutorials ",
number: 32,
header: 'Learn React',
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
imageUrl: 'http://formatjs.io/img/react.svg'
},
{
title: "See tutorials ",
number: 12,
header: 'Learn Gulp',
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
imageUrl: 'https://raw.githubusercontent.com/gulpjs/artwork/master/gulp-2x.png'
}
]
};
Next, let's add the following component to our app.jsx:
var ThumbnailList = React.createClass({
render: function() {
var list = this.props.thumbnailData.map(function(thumbnailProps) {
return <Thumbnail {...thumbnailProps} />
});
return <div>
{list}
</div>
}
});
Lets talk about what is weird here:
- var list
- First, we'll see we are using some functional programming by calling map on 'thumbnailData'. You'll notice that we pass thumbNail data into this component from our options.
- Second, within the Thumbnail component we see '{...thumbnailProps}', this is called spread attributes, and the '...' is called a spread operator 1. the spread operator actually exists in ES6 on arrays, and JSX is trying to take advantage of the syntax 1. but this spread attribute is used to pass through all the data in a more concise matter instead of passing them through, one attribute at a time.
- Finally the return at the bottom is simply returning the list of Thumbnail components we just created in a list.
Now let's update our element:
var element = React.createElement(ThumbnailList, options);
React.render(element, document.querySelector('.container'));
So if we run:
$ gulp
When our page opens we should see our two thumbnail components on the page. Thank you for reading my blog, and I hope this tutorial has been helpful. Please feel free to reach out for any help or feedback.