Home Web Development Build Applications with Meteor

Build Applications with Meteor

By Dobrin Ganev
books-svg-icon Book
Subscription FREE
eBook + Subscription $15.99
eBook $39.99
Print + eBook $48.99
READ FOR FREE Free Trial for 7 days. $15.99 p/m after trial. Cancel Anytime! BUY NOW BUY NOW BUY NOW
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
READ FOR FREE Free Trial for 7 days. $15.99 p/m after trial. Cancel Anytime! BUY NOW BUY NOW BUY NOW
Subscription FREE
eBook + Subscription $15.99
eBook $39.99
Print + eBook $48.99
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
  1. Free Chapter
    Foundation of Meteor
About this book
This book starts with the basic installation and overview of the main components in Meteor. You’ll get hands-on multiple versatile applications covering a wide range of topics from adding a front-end views with the hottest rendering technology React to implementing a microservices oriented architecture.All the code is written with ES6/7 which is the latest significantly improved JavaScript language. We’ll also look at real-time data streaming, server to server data exchange, responsive styles on the front-end, full-text search functionality, and integration of many third-party libraries and APIs using npm. By the end of the book, you’ll have the skills to quickly prototype and even launch your next app idea in a matter of days.
Publication date:
May 2017
Publisher
Packt
Pages
388
ISBN
9781787129887

 

Chapter 1. Foundation of Meteor

 

Foundation of Meteor


Meteor is an open source web and mobile development platform, simplifying the process of building applications using only one programming language--JavaScript.

What is included in Meteor?

  • Server: As a full-stack platform needs a web server, Meteor runs on top of Node.js, and we get all the benefits of using the Node, such as non-blocking I/O event driven architecture, an enormous amount of open source packages via NPM, plus we don't need to switch the language from the backend to the frontend.
  • Database(s): Meteor comes with MongoDB in a universal way. We get a light copy of MongoDB on the browser called Minimongo. Both the databases are in sync in real-time out of the box, which means that the UI can be updated even before the data reaches the server, and that is one of the most compelling features of the platform.
  • Communication: How do the client and server talk to each other? The communication is done via DDP (Distributed Data Protocol), which is an RPC (Remote Procedure Call) protocol built on top of WebSockets instead of HTTP. Due to the bidirectional communication nature of the web sockets, Meteor is a real-time platform by default.
  • Frontend UI frameworks: Meteor was using Blaze as its primary template engine, which is Meteor's implementation of Handlebars; however, it also ships with support for Angular and React currently.

Now you must be wondering how all these technologies are glued together. On a very high level, the way Meteor works is that the server publishes channels and the client subscribes to those channels, then all updates from the client can update the server in real time and the other way around--updates on the server can update the client.

Now, let's look at what else is included in Meteor:

  • There is also a native for Meteor package management, called Atmosphere, where you can find tons of useful packages. Note that all Atmosphere packages will be moved to NPM in the future.
  • ECMAScript 6 or ES6 is the major upgrade of JavaScript language, and you can code in ES6 in any of your js files. There is no need for configuring anything like babel, webpack plugins, dev servers, and task runners.
  • Any changes on the server or the client create a build automatically for you, and there is no need for browser refresh or manual server restarts.
  • Throughout the book, we will be using React expect for Chapter 8Build a Chatbot with Facebook's Messenger Platform, where we will use Angular 2. With Meteor, there is zero effort to start writing React apps. There is no need for any babel presets or anything else. The support for JSX extension comes with the default ecmascript package.

In this chapter, we'll be looking at the following topics:

  • Downloading and installing Meteor
  • Installing packages with NPM and Meteor
  • Overview of React's API
  • Creating an example application with React and Meteor
 

Setting up the development environment


Installing and running Meteor is extremely easy.

For Linux and iOS, all you need is the terminal and cURL. cURL is basically a command-line tool that we can use to move data with URL syntax, such as a GET, POST, and more, all directly from the terminal.

For Windows users, Meteor comes with an installer. You can download it from https://www.meteor.com/install">https://www.meteor.com/install. All the commands in the book are executed in a Linux terminal; just skip the sudo command and execute the commands as administrator if you are on Windows.

If you don't have cURL installed, open your terminal and install it with the following commands:

  1. Run update as a superuser:
>> sudo apt-get update
  1. Install cURL:
>> sudo apt-get install curl
  1. Verify the installation:
 >> curl --version
  1. Once you have cURL installed, installing Meteor is easy as it's a one line command:
>> curl https://install.meteor.com/ | sh

This will download the latest version of Meteor, and it will install it globally on your machine. Node.js, NPM, MongoDB, and all other default packages will be inside the .meteor directory.

The final installation looks like this:

Meteor 1.4.4.2 has been installed in your home directory (~/.meteor).
Writing a launcher script to /usr/local/bin/meteor for your convenience.
This may prompt for your password.

In Chapter 9, Build Internet of Things Platform, we will build Node.js apps connecting to a Meteor app. If you don't have Node.js and MongoDB and you want to run them outside Meteor, here's a list of commands and installing scripts that you might find useful:

Install Node.js with cURL

curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -

sudo apt-get install -y nodejs

Uninstall Node.js

sudo rm /usr/local/bin/{node,npm}

Update node with NPM

sudo npm cache clean -f sudo npm install -g n sudo n stable

Update to specific version with NPM

sudo n 4.4.4

Check the version of Node.js

node -v or node --version

Check the version of NPM

npm -v or npm --version

Install cURL and check its version

sudo apt-get update

sudo apt-get install curl

curl --versionc

Uninstall cURL

sudo apt-get remove --auto-remove curl

Purging cURL config data

sudo apt-get purge --auto-remove curl

MongoDB install(Ubuntu)

sudo apt-get update

sudo apt-get install -y mongodb-org

MongoDB version

mongod --version

Stop MongoDB

sudo service mongod stop

Restart MongoDB

sudo service mongod restart

Remove MongoDB

sudo apt-get purge mongodb-org*

Remove Data Directories

sudo rm -r /var/log/mongodb

sudo rm -r /var/lib/mongodb

The following are the Meteor scripts:

Install Meteor

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

Check the Meteor version

meteor --version

Update Meteor to the latest version

meteor update

Check the Node.js version in Meteor

meteor node -v

Create a Meteor App

meteor create app_name

Add an Atmosphere package to a Meteor app

meteor add package_name

Remove Atmosphere package

meteor remove package_name

List all the Atmosphere packages

meteor list

Install an npm package

meteor npm install package_name --save

List all the npm packages

npm list

Run a Meteor app on a specific port;

the default is 3000

meteor --port 2000

Launch the MongoDB shell in a meteor app

in the app directory execute meteor mongo

Show all databases from the MongoDB shell

show dbs

Switch to a database

use database_name

Show all collections in a database

show collections

Reset Meteor app

meteor reset

 

Building a Meteor app


The steps for creating a meteor app are as simple as the installation:

  1. Open your terminal and change your directory to where you want to have your app installed. With the meteor command line interface (CLI), we can create an app with just one command:
        >> meteor create <appname>

You can name it as anything you want; I am naming mine timerapp. We'll go through the steps of creating a basic timer, updating the time from the server side to the client in real time:

            >> meteor create timerapp

The meteor create appname command installed all packages and libraries specified in the .meteor folder in the app directory. In Meteor, the packages can be installed from Atmosphere and NPM, and there are two places where you can see what is installed by default.

Atmosphere packages are specified in ./meteor/packages. All native npm packages' metadata is in the package.json file.

FoldersIf you go into your app directory, you will note that Meteor created three folders and two files: client, server, .meteor, package.json, and .gitignore:

  • client: This is for all client-side code.
  • server: This is for all server-side code.
  • .meteor: This refers to all the core functionality of meteor: packages, databases, and many more.
  • package.json: This includes all NPM installed and saved packages.
  • .gitignore: This will ignore before the commit the specified files.
    1. cd to that app directory:
            >> cd timerapp

    To start the server, run the following command:

            >> meteor

    After some installation logs in the terminal, you'll see something like this:

            => Started proxy.
            => Started MongoDB.
            => Started your app.
            => App running at: http://localhost:3000/

    Note

    You can also start the app with npm start. This will execute the start script from package.json. "scripts": {"start": "meteor run"}. You can start meteor in another port by passing port as argument, for example, $ meteor --port 2000 . in case you have the 3000 port in use.

    1. Open the project in any text editor of your choice.

    In my setup, I am using Atom https://atom.io/ with the Facebook package Nuclide https://nuclide.io/. There are other very good editors, such as Sublime Text, Visual Studio Code, WebStorm, Brackets, and many more.

    The app skeleton, created by default, is nice and minimal. In the client and server folders, there is a startup JS main.js file. All this comes by default, and you do not need to create additional configs, specify entry points of the application in different environments, dev servers, plugins, and so on.

     

    The frontend with React


    The best way to start with React is by modifying and extending a Hello World example. There is a basic template available in the Facebook documentation.

    For simplicity, you don't need a server to get started with React; you can load it and explore it as an HTML document by opening it in your browser.

    Create a basic HTML page and place the scripts into the head tag:

    <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
      <script 
    
    src="https://unpkg.com/react@latest/dist/react.js">
      </script>
      <script 
    
    src="https://unpkg.com/react-dom@latest/dist/
      react-dom.js"></script>
      <script 
    
    src="https://unpkg.com/babel-standalone@6.15.0/
      babel.min.js"></script>
    </head>

    With the preceding scripts, we loaded react and react-dom and the third script--babel--will make (transpile) our ES6 and JSX scripts compatible with the browsers.

    Also, we can render our first component in the body tag:

    <body>
    <div id="root"></div>
    <script 
    
    type="text/babel"> //this will make ES6 code and React Jsx compatible with the browser.
    
    
    ReactDOM.render(<h1>Hello, world!</h1>, 
       document.getElementById('root'))
    </script>
    </body>

    There are two ways to define components in React: as plain JavaScript functions or as an ES6 class that extends from React.Component.

    Let's look at a basic ES6 class component:

    class Greeting extendsReact.Component
    
    {
      render() {
        return <h1>Hello, {this.props.name}</h1>;
     }
    }

    In the preceding code, we have an ES6 class Greeting that extends from React Component class; then we defined a render method that returns HTML tags. HTML tags in JavaScript is the special thing that comes with React. In essence, it is JavaScript XML (JSX) that Facebook added to React to make it more descriptive, and it also saves typing.

    You can use plain JavaScript but many developers, including myself, find it actually easier to write HTML into the JavaScript.

    Next, paste the Greeting component just above the ReactDOM.render line:

    class Greeting extends React.Component {
    render() {
        return <h1>Hello, 
    
    {this.props.name}</h1>;
      }
    }
    ReactDOM.render(
      <h1>Hello, world!
    
    </h1>,document.getElementById('root')
    )

    If you save your file and refresh your browser, you'll see that nothing changed. To render a component, you need to attach it to an actual DOM element or add it to a parent component that can render it.

    The idea of React is that we can build components or blocks and put them together to assemble complex user interfaces. Another thing you may find different is that the data flow between components is not that well prescribed like other frameworks. React itself has no actual strict pattern on how that should be done.

    However, the intention is to have the data always flowing from top to bottom in one direction, or unidirectionally as many refer to it, like a waterfall. Top-level components can pass data to their child components in one direction; if you want to update the data of a child component, you'll need to update it in the parent and pass it down again. Let's see how this works.

    Here's how we can render the Greeting component that we created:

    ReactDOM.render(
    
    
    <Greeting name="Joe"/>,document.getElementById('root')
    );

    We added the Greeting component as a <Greeting/> element, and we also passed a parameter, called name, with the value Joe.

    Save the document, refresh the browser, and see what it does.

    The properties or the props in the components are the way we pass data to components and the parameter name is accessible from the Greeting component as this.props.name.

    If we want to render many instances of the Greeting component, for example, we need a parent component that can render multiple child Greeting components:

    class App extends React.Component {
      constructor(props) {
      super
    
    (props);
      console.log(props); // array of three children components
    }
    render() {
    
    
    return (
       <div>
         {this.props.children} // render the children components
    
    
    </div>)
      }
    }
    const Greeting = ({ name}) => (
      <div>{name}
    
    </div>
    )

    Here the parent App component wraps and renders many children Greeting components:

    ReactDOM.render(
     <App>
         <Greeting
    
    name="Joe"/>
         <Greeting name="Tony"/>
         <Greeting name="Harry"/>
    
    
    </App>,document.getElementById('root'))

    The React's state

    Besides the flexibility of decoupling your development with reusable components, another powerful feature of React is in its component state. Every React component comes with an internal state.

    If the state of a component changes, the render method will fire and re-render the component. One thing that's very different from other frameworks is that React will re-render only the changes and nothing else.

    Also, it does so in a very efficient way, and it doesn't have to touch the DOM for searching before making any changes. What is happening in the back is that JSX actually represents the DOM in JavaScript, and all the updates are happening on the script site in memory first; then it will do some checks, then batch the changes and, finally, it will commit them to the DOM.

    Adding state to a stateless function component

    What is a state in React's components?

    Components can be declared as pure JavaScript functions, and they are called Stateless, such as this one:

    function Greeting({ hello }) {
          return <div>{hello}</div>;
    }
    

    Alternatively, you can write the preceding code as an ES6 arrow function:

    const Greeting = ({ hello }) => (
        <div>{hello}</div>
    )

    Every component can hold internal encapsulated data, and we call this a state of the component. If you want to add a state to a stateless component, you should define it as an ES6 class.

    Before adding an ES6 constructor and super methods to the stateless components, we can overview what an ES6 constructor is and what the super method does in ES6 classes.

    In ES6, we can create a class, such as the following:

    class Component {
    constructor(props){
       this.props = props;
      }
    }

    The names of the parameters and methods are named as React's once. This is not from the React library source.

    We can add a method called render, as mentioned in the following code:

    class Component {
       constructor(props){
       this.props = props;
    },
    
    render() {
       return this.props;
      }
    }

    In an ES6 classical way, we can extend the base/parent class Component:

    class Greeting extends Component{
    constructor(name){
        super(name) // passing the value to the parent class which gets
        assigned to the props
        console.log(super.render()) // with the super method we can call the  functions from the parent class      
        console.log(this.render()) // or directly as this.render
    }
    }

    In a classical way, we can create a new instance of the Greeting class, like this:

    let greet = new Greeting('Joe');
    console.log(greet.render()) // have an access to the parent method render

    We can create a render() method with the same name in the child class:

    class Greeting extends Component{
         constructor(name){
         super(name)
         this.name = name;
         console.log(super.render())
    }
     render() {
       return 'Hi ' + this.name;
      }
    }
    let greet = new Greeting('Harry');
    console.log(greet.render()) // child overrides the parent

    Inheritance versus composition

    Facebook and the React community encourage the use of composition over classical inheritance. It can be said that any other pattern to reuse code is considered anti-pattern in React. A lot more can be said about that, but React has been heavily used in production at Facebook without using inheritance for sure. In such a large-scale application, the advantage of building independent pieces and combining them to form a complex functionally is what made React so popular. Components can be moved around, organized by common functionality; they can be well tested and refactored without much of a risk of breaking other parts of the system.

    Extending from the React.Component:

    class Greeting extends
    
    React.Component {
      constructor(props){ // ES6 class constructor
      super(props) // ES6
     }
      render() {
       return <h1>Hello, {this.props.name}</h1>; //local
      }
    }

    Instead of creating a new Greeting instance, we are adding it as a <Greeting/> tag:

    ReactDOM.render(
    <Greeting name="Johny"/>,document.getElementById('root'))

    Some components can be strictly presentational; others may not know who can be their children components in advance. Many namings later came from the community, Smart and Dumb components, Containers and Components, functional and classical.

    How React is used it's all up to the developers, the team, and the organization. It's a very powerful and unopinionated library and can be used along with other frameworks.

    Adding a state to a component

    One can say that React barely has any API. It has about 9-10 methods and that is all we get.

    The State is one of the main APIs in React. The best place to define the initial state of a component is in the class constructor.

    Create a class component and initialize its state:

    class Button extends React.Component 
    
    {
       constructor(props){
       super(props)
    this.state = {text: 'OFF'}
       this.handleClick = this.handleClick.bind(this)
    }
      handleClick(){
    this.state.text === 'OFF' ? this.setState({text: 'ON'}) :
    this.setState({text: 'OFF'})
    }
     render() {
      return (
        <button type="button" onClick={this.handleClick}>
      {this.state.text}</button>)
      }
    }

    This is an example of an internal state of a button that changes its text on user click (it toggles between ON and OFF).

    A few things are required for that component to maintain a state:

    • We defined the state in the class constructor method. This is the first entry of the class that will be executed. We can think of that definition as the default state of the component.
    • We created a handleClick() method and bound it to the this class in the class constructor. It will fire when the user clicks on the button.
    • In the handleClick method, we used one of the React's APIs--this.setState--and based on the comparison of the current state, we set our new state.

    Note

    React is built with functional purity in mind, and if you set the state directly as this.state.text = 'OFF', the component will not re-render.

    • In the button, we added a simple JavaScript event--onClick. Here, React has a slightly different syntax on events; it uses camel case. onClick becomes onClick.

    The second form of the setState() method is passing a function in the state instead of an object; in the callback, we get the previous state:

    this.setState
    (function(prevState) {
    return {
       text: prevState.text === 'OFF' ? 'ON' : 'OFF'
      };
    });

    Alternatively, an arrow ES6 function can be used:

    this.setState((prevState) => ({
      text: prevState.text === 'OFF' ? 'ON' : 'OFF'
    }));

    Other React methods.

    A few other important React APIs are the component life cycles methods:

    class Greeting extends React.Component {
        constructor(props) {
        super(props);
        console.log('constructor');
    }
    componentDidMount() {
       console.log('componentDidMount');
    }
    componentWillUnmount() {
       console.log('componentWillUnmount');
    }
    render() {
       return (
       <div>
          <p>{this.props.name}</p>
            {this.props.children}
       </div>)
     }
    }

    Let's test these life cycle methods by adding a simple button to the body of the HTML:

    <button onclick="umountComponent()">Unmount</button>

    Also, we can define that function in the JavaScript tag, as follows:

    function umountComponent(){
    ReactDOM.unmountComponentAtNode(document.getElementById('root'))
    }

    When the app is loaded, the order of the events is as follows:

    1. Constructor method is called.
    2. componentDidMount() is called when the component is mounted to a parent or directly to the DOM.
    3. componentWillUnmount() is called just before the component will unmount from the DOM.

    A simple use of these events can be as shown:

    1. Constructor: Initialize the component's default state in the constructor.
    2. componentDidMount(): The component is ready. You can perform any actions at that point.
    3. componentWillUnmount(): The component will be detached from the DOM; here, you can clear any resources that may cause memory leaks.

    Meteor with React

    Starting from the client, let's create our simple app:

    1. Delete all the content of the client folder.
    2. Create the index.html file with the following content:
    <head>
       <title>Timer</title>
    </head>
    <body>
      <div id="root"></div>
    </body>
    1. Meteor will take care of the missing HTML tags. It will compile it as a template rather than serve it as an HTML document.
    2. It will throw an error if you try to add the <!DOCTYPE html> and html> tags:
          While processing files with <cdpcomment data-comment-id="2521" 
          data-comment-text="Sounds incomplete. ">">templating-compiler 
          (for target web.browser):
    
          client/index.html:1: Expected one of: <body>, <head>, <template>.

    Since we are using only React, we don't need to have the blaze-html-templates package installed.

    Adding and removing atmosphere packages in Meteor

    There are two ways to add and remove atmosphere packages in Meteor: directly add it in .meteor/packages or use the meteor add or meteor removecommands.

    We will remove blaze and jquery for this example:

    >> meteor remove blaze-html-templates

    This will result in the following terminal:

    blaze-html-templates removed from your project
    caching-compiler removed from your project
    caching-html-compiler removed from your project
    templating removed from your project
    templating-compiler removed from your project
    templating-runtime removed from your project
    templating-tools removed from your project

    Now if you run your app, you will note that nothing is loaded. You'll need to install the html-static package to let Meteor load a static HTML file.

    You can install it with the following command:

    >> meteor add static-html

    It will add all the needed dependencies:

    caching-compiler added, version 1.1.8
    caching-html-compiler added, version 1.0.7
    static-html added, version 1.1.13
    templating-tools added, version 1.0.5
    Remove Jquery by deleting it in the package file (.meteor/packages)
    jquery@1.11.10 # Helpful client-side library

    You can add and remove packages even if the server is running. Meteor will restart it automatically when a package is removed or added.

    The next step is directories and files:

    • Create index.js in the root of the client folder. This will be our start up file where we can import and render the rest of the components.
    • Create the components folder. For a small demo app like this, we can keep the components in a folder components.
    • In folder components, create a Timer.js file, you can use and also Timer.jsx; Meteor will transpile JSX into JavaScript by default. Both ways are fine.

    Install react and react-dom with npm:

            >> npm install react --save
            >> npm install react-dom --save

    In the Timer.js file, let's define our component:

    import React from 'react';
    import ReactDOM from 'react-dom';
    class Timer extends React.Component {
      constructor(props) {
      super(props);
    }
    render() {
      return (<div>
             <p>Timer</p>
             </div> )
      }
    }
    export default Timer;

    It is a class component that will display the time pushed in real time from the server. The only difference between preceding examples and this one, is that we exported that component to use it in other components.

    Now, let's import and render it in the index.js file:

    import React from 'react';
    import {render} from 'react-dom';
    import Timer from './components/Timer'
    render(<Timer/>, document.getElementById('root'))
    
    

    First, let's create the functionality of the app on the client; then we can start pushing the data from the server.

    Initialize the state in the constructor and set a new state every second:

    constructor(props) {
       super(props);
    this.state = {time: 0};
    } 
      componentDidMount() {
    setInterval(() => this.setState({time: new Date().toLocaleString()}), 1000);
    }

    Also, we have the following code in the render() method:

    render() {
        return (<div>Time : 
    {this.state.time}</div>)
       }

    When the component mounts, we set a new state every second. This will force the component to re-render and display the latest state.

    To exercise the idea of the state and the props, we can now create a child component that the Timer component will render and pass its state as prop.

    Create a child component in the components folder, called TimerDisplay:

    class TimerDisplay 
    extends React.Component {
        constructor(props) {
         super(props);
      }
     render() {
        return 
        (
           <div>Time : {this.props.time}</div>
        )
       }
    }
    export default TimerDisplay;

    The TimerDisplay will receive and render the data through the props.time. It can be a stateless presentational component, and it can be defined as a function instead of a class:

    import TimerDisplay from './TimerDisplay';
    class Timer extends React.Component {
       constructor() {
       super();
    this.state = {time: new Date().toLocaleString()};
    }
       componentDidMount() {
    setInterval(() => this.setState({time: new Date().toLocaleString()}), 1000);
     }
     render() 
    {
       return (
       <div>
       <TimerDisplay time={this.state.time}/>
    </div>)
      }
    }
    export default Timer;

    Here, the parent component, Timer, re-renders every time its state changes, and then renders the child component, TimerDisplay, by passing its state as props.

    What will happen if we add another TimerDisplay, but this time with a static value:

    render() 
    {
      return (
        <div>
         <TimerDisplay time={this.state.time}/>
         <TimerDisplay time='today'/>
      </div>)
    }

    To see the power of React in action, open the console in Chrome and press the Esc key then go to Rendering and click on the checkbox Paint Flashing. You will note that even if we rendered both TimerDisplay, only the one that has its value changed is re-rendering.

    Integrating React with Meteor's reactive data system

    In the preceding example, the data passed to the child component via props was generated in the parent component itself in the setInterval function. In order to render React components on Meteor's data change, we need to create a component container.

    The steps are as follows:

    1. Add react-meteor-data and react-addons-pure-render-mixin npm packages using the following command:
            >> npm install react-meteor-data --save
            >> npm install react-addons-pure-render-mixin --save
    1. Import createContainer into the Timer.js component:
            import React from 'react';
            import TimerDisplay from './TimerDisplay';
            import { createContainer } from 'react-meteor-data';
    1. Export the container function instead of the component:
            export default createContainer(() => {
            return {
               time: Time.find().fetch()
              };
            }, 
           Timer);

    The first parameter is a callback function that returns the result as an object named time, and the second parameter is the Timer component. The way it works is that on any changes in the browser database Minimongo, the data will be fetched and passed to the component as props (time in our case).

    To break this down, refer to this:

    1. We defined Time as a MongoDB collection.
    2. find() is a MongoDB method to query records (records are called documents in MongoDB) from the collection. If there is no query specified, will return cursor for the first 20 records by default.
    3. Adding the fetch() method will return the documents as an array.

    Meteor allows us to create a collection directly in the code:

    Time = new Mongo.Collection('time');

    Explore MongoDB in the Meteor shell

    You can access all the application data with the Meteor MongoDB shell.

    Open another terminal, cd to the app directory, and start the MongoDB shell.

    Note

    The app should be running at the same time.

    >> meteor mongo

    Show all the databases in MongoDB:

    >> show dbs

    The default database for the app is named meteor; switch to the meteor database:

    >> use meteor

    Display all collections in the database:

    >>show collections

    The show collections command will not return any results.

    The reason is that we created a collection on the client side only. This collection exists in Minimongo, and it is in the browser's memory. If we refresh the page, the collection and the data will be gone.

    In order to create the same collection and persist data into MongoDB, we have to execute the exact same Time = new Mongo.Collection('time'); on the server. As soon as we do that, both the collections will be in sync and the data will be persisted into the database.

    For now, we don't want to save the timer data on the server; we only want to take advantage of the Meteor server to client real-time communication.

    Publishing and Subscribing

    The way we can get real-time updates from the server is through the Publishing and Subscribing messaging pattern of Meteor.

    The server publishes an event and on the other side, the client subscribes to that event and listens to data changes.

    On the server, in our case in the server/main.js file, we can publish an event in a very simple way:

      import { Meteor } from 'meteor/meteor';
      Meteor.startup(() => {
         // code to run on server at startup
     Meteor.publish('time', function() {
         ...
        });
    });

    The publish function takes two arguments: name of the collection and a callback function that will be executed on each subscription from the client.

    On the client, we can subscribe to it as shown here:

    Meteor.subscribe('time');

    All updates from the server will push an update to Minimongo collection on the client. The subscriber can also pass a parameter as a second argument and/or have subscription handlers as callback functions:

    Meteor.subscribe('time', id);

    Also, the subscription handlers look like this:

    Meteor.subscribe('time', {
    
     //called when data is availble in  Minimongo
       onReady: function() {
       },
        // called on error
       onError: function() {
       },
       // called when the subcription is stopped. 
        onStop: function () {
       }
    });

    Here's the server-side code of the subscription:

    import { Meteor } from 'meteor/meteor';
    import { Random } from 'meteor/random';
    
    Meteor.startup(() => {
    // code to run on server 
    
    at startup
    Meteor.publish('time', function() {
       let self = this;
       const newTime = () => {
       let 
    
    id = Random.id();
       let time = {
        time: new Date().toString()
     }
       self.added
    
    ('time', id, time);
    }
    Meteor.setInterval(function() {
        newTime();
      }, 1000);
    });

    What we did is covered in the following points:

    1. We created a publisher with a collection called time.
    2. We used one of the Meteor's timer functions, setInteval(), to call a newTime() function every 1000 milliseconds or one second.
    3. In the newTime() function, we created an ID of the document and the document as the current time.
    4. We then called the added method, which will notify the subscriber that we added a new document to the time collection.

    The client-side code is as follows:

    Time = new Mongo.Collection('time');
    class Timer extends React.Component {
         constructor(props) 
    
    {
         super(props);
        Meteor.subscribe('time');
    }
    render() {
       return 
    
     <TimerDisplay time={this.props.time}/>;
      }
    }
    export default createContainer(() => {
     return 
    
    {
        time: Time.find().fetch()
      };
    }, Timer);

    This is what we did here:

    1. We created a collection called time. The collection is created locally in Minimongo. If we don't create the same collection on the server, it will be only in the browser's memory.
    2. In the class constructor, we subscribed to the dataset time published on the server.
    3. In the render method, we rendered the TimerDisplay component as we passed time as props.
    4. At the end, we created a Meteor React container that listens to data changes, fetches the latest data from the collection, and passes it down to the component as props.
    Improvements in the current code

    In both the server and the client, we didn't provide an unsubscribing mechanism. For example, if you close the browser, the server will continue calling the newTime() function indefinitely.

    Meteor.publish() provides some other useful APIs. When the client is subscribed for the first time, we can send a notification that the initial dataset was sent using this.ready(). This will call the onReady callback on the client.

    We can also unsubscribe the client with this.stop() or listen whether the client subscription is stopped.

    The publisher on the server:

    Meteor.publish('time', function() {
       let self = this;
       self.added('time', id, time); // notify if record is added to the collection time
      let interval = Meteor.setInterval(function() {
          newTime();
      }, 1000);
     this.ready(); // 
    
    notify that the initial dataset was sent
       self.onStop(function () {
       self.stop()
       console.log('stopped called')
       Meteor.clearInterval(interval); // clear the interval if the the client unsubscribed
      });
    });

    The subscriber on the client:

    const handle = Meteor.subscribe("time", {
       onReady: function() { 
    // fires when this.ready() called on the server.
      }
    });
     handle.stop() // will call onStop(callback) on the server.
     handle.ready() // returns true if the server called ready()

    The clientTimer component:

    Time = new Mongo.Collection('time');
    const handle = Meteor.subscribe('time');
    class Timer extends React.Component {
        constructor(props) {
        super(props);
     }
     shouldComponentUpdate() {
        return this.props.handle.ready() && this.props.time.length > 0;
     }
     componentWillUnmount() {
       this.props.handle.stop();
     }
     render() {
        return <TimerDisplay time = { this.props.time }/>;
     }
    }
    export default createContainer(() => {
      return {
        time: Time.find().fetch(), handle: handle
      };
    }, Timer);

    Here, we passed the subscriber's handle as a prop to the component and in shouldComponentUpdate, we check whether the publisher sent the first dataset and whether it has any records. If yes, it will render the imerDisplay component.

    When we unmount the component, we send a notification to the that we stopped the subscription.

     

    Summary


    We went over the foundation of Meteor and overviewed its core components. High-level databases, servers, package managers, and its communication protocol (Distributed Data Protocol). On a high level, we now understand how the platform works.

    We installed Meteor and created a sample app with the Meteor CLI. Then, we went over the default app skeleton and some of the included Atmosphere and NPM packages.

    On the frontend, we overviewed the basics of React, its data flow, and component architecture. Then, we created a sample real-time server to client communication app and got familiar with the core functionality of the Meteor Publish and Subscribing API.

    In the next chapter, we will get more familiar with the Meteor Methods, Schema, and validation by building a simple shopping cart app, and we will continue exploring data handling and reactive rendering with React on the frontend.

    About the Author
    • Dobrin Ganev

      Dobrin Ganev is a software developer with years of experience working in various development environments, ranging from finance to business process management. In recent years, he has focused on geospatial development and data analytics using languages such as JavaScript, Python, Scala, and R. He has extensive knowledge of open source geospatial and the ESRI platform. Currently, he focuses on big data and its applications across broad industries and sectors. Founded in 2015, chorStream Inc. (www.chorstream.com) is a software development firm centered around using big data and big data technologies to help clients work with and leverage large and diverse volumes of data. Dobrin, as a co-founder of chorStream Inc, has worked with an accomplished team of professionals to create and bring to market an application framework (similar to a web app builder) that end users can use to build custom and focused applications without needing any development skills. He is also skilled in Node.js, Meteor, front-end React, and Angular 1, 2, and 4.

      Browse publications by this author
    Latest Reviews (3 reviews total)
    Me gusta mucho el desarrollo de apps web con el paradigma de programación reactiva.
    Seems to me an excellently written book for intermediate Meteor and React users. The previous reviewer wrote: "...code snippets are shown but not shown which file they go in, they also have extracts of code snippets but not the whole snippet so it's pretty confusing getting anywhere with the book". Wrong! The book consists of 9 chapter-projects. The code for each chapter project is given in full, and works out of the box. You just have to download the full code. It is naive to expect from a serious programming book to duplicate all the code on the book's pages. It is not necessary to show which code snippet, as discussed in the book, goes to which file.. It is actually a waste of space and effort. Each project consists of tens of files for you to follow. You can only grasp each project and its organization by opening and studying it in a code editor. I am in the middle of the book, and I learn a lot.
    Starts off good then just seems to 'blabble' along, code snippets are shown but not shown which file they go in, they also have extracts of code snippets but not the whole snippet so it's pretty confusing getting anywhere with the book
    Build Applications with Meteor
    Unlock this book and the full library FREE for 7 days
    Start now