codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Follow publication

Meteor + React Tutorial

From installation to CRUD app

Introduction

In this tutorial, I will guide you from installation all the way through to a finished and working CRUD app.

I will show you how to code a simple Todo app with its own database, giving you a basic knowledge of React which can be applied to many other things.

Before I continue, I’d like to add that I’m still learning, so if there’s anything that could be explained better or improved then I’m completely open to your feedback.

This tutorial is aimed at people who have already learnt HTML, CSS and some basic Javascript and are looking to expand their knowledge and pick up some different frameworks. If you’d like to find out more about what Meteor and React are, please follow these links and have a little read through to give you a basic idea:

https://www.meteor.com

https://reactjs.org

Part 1

Install fest!

If you already have Meteor and React installed, feel free to create your Meteor app, install React and skip to Part 2.

You will need the npm package manager to get everything installed. You’ll find the npm manager by installing node.js. Click here and follow the instructions to install it. You’ll then get the npm package manager automatically.

Now hit cmd + spacebar. This will open up the Spotlight searchbar. Type terminal and press enter. This will open up the terminal where we can install everything we need to get started.

First of all, we need to install Meteor. Type the below and press enter:

curl https://install.meteor.com/ | sh

Then we can change directory (cd) to the desktop by typing the below and pressing enter:

cd desktop

Now, let’s say you’d like to call your app banana ( or whatever you’d like to call it…)

meteor create banana

Meteor will take about a minute to create your app so let it do its thing. We are going to be using React with Meteor, so once it’s done type in the below:

cd bananameteor npm install react react-dom — save

Now type Meteor. This should get it up and running and display:

app running at — http://localhost:3000/

You can copy the URL and paste it into your browser just to see if it’s working. Have a little look around, we will be deleting this boilerplate stuff anyway. If you want to stop the app running at any point, just go to the terminal and press ctrl + c together.

It’s generally a good idea to keep the app running. That way, every time you save a change you can open up your browser and check it out instantaneously, rather than having to type Meteor again and wait for it to build the app.

Part 2

Set up!

Now all that’s finished, open the app in a text editor of your choice (I’m using brackets).

In the client folder, there should be a main.html, main.css and main.js file.

In the main.html file, replace what’s inside with the following:

<head></head><body><div id=”app”></div></body>

In the main.js file, replace what’s inside with the following:

import { Meteor } from ‘meteor/meteor’;
//import Meteor library
import React from ‘react’;
//import React library
import { render } from ‘react-dom’;
//import the render function from react-dom
import HelloMeteor from ‘../imports/HelloMeteor.jsx’;
//import the React component that we haven’t created yet!
Meteor.startup(() => {render(<HelloMeteor />, document.getElementById(‘app’));});

Now we need to create that HelloMeteor component. To do this, we need to make an ‘imports’ folder (make sure it’s all lowercase).

The imports folder will house all of our components. Please note that this isn’t an arbitrary name, the imports folder has a specific meaning for Meteor. If you’re interested in why read below, if not you can skip this section.

In the past, Meteor would ‘eagerly’ (or automatically) load all of the code in our application for us. With imports and exports, we can conditionally load files only where they’re needed. This makes our code a little more predictable and can help to reduce the weight of our application at runtime.

To aid in this process, Meteor now includes support for the imports directory. Unlike the /client and /server directories where all code is loaded automatically following a specific load order, any code within the project’s /imports directory is not loaded automatically. This means that anything placed in this directory must be loaded explicitly in the application. Otherwise, our application won’t see it.

Now thats over and done with we can start to code.

Part 3

Let’s code!

So now let’s create our HelloMeteor.jsx file inside the imports folder. It’s also important to note that all components created for your application should start with a capital letter.

For the majority of your other components, this next section of code will more or less always look the same. You will be re-writing this many times (or copy/pasting it) so you will learn the structure eventually:

import React from ‘react’ — /*you always need to import react*//*here is where we can import other child components or mongo collections (database)*/export default class HelloMeteor extends React.Component {render(){/*we can create variables here for conditional rendering purposes or for styling purposes*/var example = truereturn(     <div> /* this is where we put all of our jsx (basically html) if you want         to render more than one element, you should put them in a div and if you want to use javascript here it will need to go between curly braces for instance */    {example == true ? <h1>Its true</h1> : <h1>its false</h1>}    </div>    )
}
}

*Don’t forget to get rid of my comments before running the code.

If you type this code in you should see an h1 appear. Notice how the ternary operator we added into the return statement is displaying the h1 based on a conditional statement. In this case we are checking if the variable we created is true or false. This can be handy for showing or hiding certain elements based on the state of the component. This leads us to…

State

State is an object which you can use to determine how the component renders and behaves. If the state changes, the component responds by re-rendering. In other words, state allows you to create components that are dynamic and interactive.

We create the state object as follows:

constructor(){
super()
this.state = {
}
}

To give you a basic example of how the state works, delete the previous code and type the below into your project:

import React from ‘react’export default class HelloMeteor extends React.Component {constructor(){
super()
this.state = {
example: true
}
}
changeState(){ var example = this.state.example
this.setState({example: !example})
}render(){ return (
<div>
<button onClick={this.changeState.bind(this)}>Click me!</button>
{this.state.example == true ? <h1>Visible</h1> : null}
</div>
)
}
}

So when the button is clicked it activates our changeState() function. We then take the current state and store it in a variable. The next step is setting the state. Using the bang operator, here we set it so that whenever the button is clicked it will change to the opposite of the current state. This in turn re-renders the jsx. As we have a conditional checking the state each time, whenever the state doesn’t equal true it will render null, causing our h1 to hide.

Now we have our first component and a few of the basic concepts down, let’s begin coding our Todo app.

Part 4

Coding the app!

Let’s start with an input that stores whatever we type to the state. We can achieve this by applying the onChange event listener to the input. Delete the previous code and type the below:

import React from ‘react’export default class HelloMeteor extends React.Component {constructor(){
super()
this.state = {
todo: “”
}
}
handleChange(e){
var todo = this.refs.input.value
this.setState({todo: todo})
}
render(){ return (
<div>
<input onChange={this.handleChange.bind(this)} ref=”input”/>
<h1>{this.state.todo}</h1>
</div>
)
}
}

If you want to read more about React event listeners, follow the below link:

https://appendto.com/2017/01/react-events-101/

Similar to the way you might use document.getElementById() with basic javascript, React has something called refs. You give a ref to the element that you wish to reference by typing ref= “name”. Then to recall the information we can just type this.refs.name.value. You could also use e.target.value if you wish.

Now we have this working, we just need to push that information to the database with some mongo syntax, which is relatively easy to do.

First we need to create a mongo collection. You can think of this as just a grouping of data. For example, if you were to create an e-commerce site, you might have one collection created for users profiles and another collection for products. We need to put the mongo collections inside the api folder, inside the imports folder.

To do this, create a folder inside the imports folder and name it - api. Inside the api folder, create a file called todos.js. It’s inside this file that we’ll create our mongo collection with the below syntax:

import {Mongo} from ‘meteor/mongo’export const todoContainer = new Mongo.Collection(‘todos’)

We’ll need to import this to our main.js file located in the server folder:

import {todoContainer} from ‘../imports/api/todos’

And in our HelloMeteor file at the top of the page, import the collection so we can use it.

import {todoContainer} from ‘./api/todos’

Just a little note, make sure that your collections have different names to your components.

Now we can add some information to our database. First, create a button below the input as follows:

<button onClick={this.handleClick.bind(this)}>Add</button>

Notice that I’ve attached a function to it which deals with adding the information to the database.

Now create this function somewhere above render():

handleClick(){

var todo = this.state.todo
todoContainer.insert({todo},(err,done)=>{
console.log(err + “ id = “ + done)
})
this.setState({todo: “”})
this.refs.input.value = “”
}

First, store the current state in a variable, then insert that variable into our mongo collection. Once this is finished, we clear the state and the input for the next entry.

It’s as easy as that. If you’d like to take a look at the information you’ve added to the database, you can do the following: open the terminal, click on shell from the top menu, open a new tab (basic or whatever you want), type meteor mongo and hit enter. If you then type ‘show collections’, you can view a list of your current collections. In our case you would type db.todos.find({}), and that will give you a print out with the ID and the information you added.

Now we want a way to list the information we’ve added. To make this simple, I’m going to create another component that handles the part where we grab the information from the database and display it to the user.

In the imports folder, create another component called TodoList.jsx and type out the below code:

import React from ‘react’import {todoContainer} from ‘./api/todos’export default class TodoList extends React.Component {
constructor(){
super()
this.state = {
list: []
}
}
render(){
return (
<div>
</div>
)
}
}

Notice we have imported our collection so we can grab the todos and we’ve created a state called list which is equal to an empty array. This is where we’re going to put our collection. Before we do that, we need to import this component to our HelloMeteor so they are connected. At the top of HelloMeteor paste the below code:

import TodoList from ‘./TodoList’

At the bottom, directly below the add button, place our new list component as jsx:

<TodoList/>

Now they’re connected, let’s get the information from our collection and display it on the page so the user can read it. To do this, go back to the TodoList.jsx file.

To access our collection, we will need to use a lifecycle method componentWillMount(). This method is called once (before the component renders) and gives us a chance to update the state and in general, just prepare the component before it renders.

Inside componentWillMount() we’re going to use Tracker.autorun to find and fetch the collection. Once we’ve fetched the collection, we’ll place it in our state as an array where it will be accessible to display. Place the below function anywhere above render():

componentWillMount(){
Tracker.autorun(()=>{
var todos = todoContainer.find({}).fetch()
this.setState({list: todos})
})
}

Once you have that in place, let’s map out the information. Place the below inside a <div></div>, inside the return (in the render function). You should see whatever you’ve added to the database appear on the screen now. If you add anything else it should automatically update the database and re-render on the page.

{ this.state.list.map((val, index)=>{
return(
<div key={index}>{val.todo}</div>
)
}) }

Now we’ll create a component for the individual todos in our list, where we can store the delete button amongst other things. Replace the div in the map function’s return statement with the following jsx:

<IndividualTodo
key={index}
id={val._id}
todo={val.todo}
/>

Notice that we’re passing the ID (for deleting purposes) and the todo (so we can display info) down to the individual todo component as props. Props is just a way of sharing information between components. This information will now be available in the IndividualTodo component through “this.props”.

As we did before with TodoList, create the IndividualTodo.jsx component and import it to TodoList.

The next part is very easy. All we have to do is import our collection, create a list to display our todo’s, create a button and hook that up to a function so that we can remove our todo’s. See below:

import React from ‘react’
import {todoContainer} from ‘./api/todos’
export default class IndividualTodo extends React.Component { deleteTodo(){
var id = this.props.id
todoContainer.remove({_id:id})
}
render(){const list = {
listStyle: “none”,
display: “inline-block”,
marginRight: “10px”,
cursor: “pointer”,
marginTop: “10px”
}
return (
<div>
<li style={list}>{this.props.todo}</li>
<button onClick={this.deleteTodo.bind(this)}>X</button>
</div>
)
}
}

As you can see, each mapped out todo will use the IndividualTodo component, each one making their unique id available through props. To make todo’s removable, use the mongo syntax .remove and reference the ID.

You should now be able to add and delete todo’s by clicking on the little x button we created next to them.

The next thing we’re going to do is create a way for the user to put a line through the todo by simply clicking on it. The way we’ll do this is by adding an extra field for the todo when it’s created. If you delete all of your todos now and go to the HelloMeteor.jsx file, inside the handle click function, create a variable called ‘done’ and set it to false. Then pass this into the insert function as below:

handleClick(){ var todo = this.state.todo
var done = false;
todoContainer.insert({todo, done},(err,done)=>{
console.log(err + “ id = “ + done)
})
this.setState({todo: “”})
this.refs.input.value = “”
}

Now that’s confirmed, we’ll need a way to update this information, for our component to read it and put a line through the todo when it equals true.

First pass ‘done’ as a prop to the IndividualTodo component:

<IndividualTodo
done={val.done}
key={index}
id={val._id}
todo={val.todo}
/>

Then go to IndividualTodo.jsx and create the below function above render(). We’ll need to access the ID and ‘done’ through props:

addLine(){
var id = this.props.id
var done = this.props.done
todoContainer.update({_id:id},{ $set:{ done: !done }
})
}

Add this function to an onClick event listener on the list item as follows:

<li onClick={this.addLine.bind(this)}>{val.todo}</li>

This is how we update our collection with mongo. Much like insert and remove, we type out our collection name then attach .update, referencing the ID we want to change. With update, we use $set to reference the value we want to change, which in our case is ‘done’.

We set ‘done’ to be the opposite of whatever it currently is, allowing us to alternate between true and false. Now all we have to do is conditionally render the list item with a different style depending on this.props.done as follows.

Delete the <li> and replace it with the below ternary operator:

{this.props.done == true ? <li style={lineThrough} onClick={this.addLine.bind(this)}>{this.props.todo}</li> : <li style={list} onClick={this.addLine.bind(this)}>{this.props.todo}</li>}

If done equals true, render out this individual todo with the style ‘lineThrough’. If it doesn’t equal true, render it out normally with the style ‘list’.

Then create the style ‘lineThrough’ below the ‘list’ style:

const lineThrough = {
textDecoration: “line-through”,
listStyle: “none”,
display: “inline-block”,
marginRight: “10px”,
cursor: “pointer”,
marginTop: “10px”
}

Check it out, you should now be able to toggle a line through each todo just by clicking on it.

That’s pretty much it. We have our todo list which we can create, read, update and delete.

Part 5

Adding styles!

Now I’m going to show you a really easy way to add animation to the Todo list.

We’re going to use the external component called FlipMove, all we have to do is install it, import it and then wrap it around our map function.

First, open up the terminal:

npm i -S react-flip-move

At the top of TodoList, type the below:

import FlipMove from ‘react-flip-move’

Then, wrap it around the map function:

<FlipMove>{ this.state.list.map((val, index)=>{
return(
<IndividualTodo
done={val.done}
key={index}
id={val._id}
todo={val.todo}
/>
)
}) }
</FlipMove>

Save it and have a little look! It should animate when you add or delete items.

Let’s add some styles now.

First, import bootstrap inside the head tag in your main.html file (find this in the /client):

<head><link rel=”stylesheet” href=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity=”sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u” crossorigin=”anonymous”></head><body><div id=”app”></div></body>

In HelloMeteor, give the add button the following className:

className=”btn btn-success”

Also, create the below styles below render().

Give the ‘center’ style to the encapsulating div, give the ‘input’ style to the input and give the ‘margin’ style to the add button.

const center = {
textAlign: “center”
}
const input = {
borderRadius: “5px”,
height: “30px”,
width: “250px”,
fontSize: “20px”,
marginTop: “20px”
}
const margin = {
marginBottom: “6px"
}

In IndividualTodo, give the delete button the following className:

className=”btn btn-danger”

Now create a file in the import folder called -todo.css and paste these styles in there:

body {
padding: 50px;
background-color: #66CCFF;
font-family: sans-serif;
}
li {
color: #333;
background-color: rgba(255,255,255,.5);
padding: 15px;
margin-top: 10px;
margin-bottom: 15px;
border-radius: 5px;
display: block;
}
li:hover {
background-color: rgba(245,245,245,.5);
}

Finally, import that stylesheet to the HelloMeteor component:

import “./todo.css”

And that’s it!

Now I’d recommend deleting everything and making it on your own, or use what you know to build something else!

✉️ Subscribe to CodeBurst’s once-weekly Email Blast, 🐦 Follow CodeBurst on Twitter, view 🗺️ The 2018 Web Developer Roadmap, and 🕸️ Learn Full Stack Web Development.

Published in codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Written by Mike Sullivan

🚀 Full-stack developer | Tech enthusiast | Wordsmith. Creating code and stories for a tech-infused world. Let's connect in the digital realm! 👨‍💻📚

Responses (1)

Write a response