in Getting Started, Tutorials

Getting Started with Meteor 1.3, React 15, and FlowRouter

With the release of Meteor 1.3, there are several key changes you will want to make in how you implement a Meteor app. The official tutorials and the Meteor Guide are great places to start learning about what’s new. However, if you are using React together with FlowRouter, you’ll find that the Meteor React tutorial does not include routing and the more advanced sample todos app uses Blaze rather than React. More importantly, there are steps in the React tutorial you specifically do not want to follow if you will be using FlowRouter. (More about that below.)

Update: As pointed out in the Meteor forums, there is in fact a react branch of the todos app. However, it uses React Router, which is another excellent routing option.

Here, we’ll fill this gap by walking through getting set up with Meteor 1.3, React, and FlowRouter, and include a few (opinionated) pointers along the way.

This is a fairly beginner-focused tutorial.  If you are already familiar with ES6, React 0.14+ and Meteor 1.3 and just want the code, here’s the completed version of the app on GitHub.

However, I recommend following along with the tutorial and creating the app on your own.

Create a project directory, set up version control, and install Meteor

Navigate to the location where you want to store your project, then create a project directory and cd into it.  In this directory, I recommend creating a “ReadMe” file and a tmp directory, where you can move files you’re no longer using in your app but maybe want to refer to later.

At this point, I recommend initializing a new Git repo, so your first commit is nice and pristine.

Here, we told Git to ignore the tmp directory we created and then created a first commit.  You might also want to start pushing your commits to Github.

Next, let’s create the Meteor app.  If you haven’t already done so, you’ll want to install Meteor first.

If all goes well, you’ll get a nice message back from Meteor suggesting that you can cd into your newly created app directory and other useful info.

Why did we create our Meteor app inside another directory?

You might be wondering why we created the app inside another directory rather than just have our Meteor app be the main project directory.  The reason for this is so that we can include files in our project that are not mixed in with the actual app files. For now, those only files are our tmp directory and a README file, but over time you are likely to find that there many other files you’ll want to store here.

Start and View Meteor in Your Browser

Next, we want to get set up for implementing our app.  First, cd into your app directory, and then start meteor by simply typing “meteor”

Open a browser window and navigate to “http://localhost:3000” This page will automatically update as you make file changes.  I also recommend displaying your browser console (here’s how to do that in chrome) and keeping the window where you just typed the  meteor command open and visible next to your browser.  Meteor will display any server log information in that window.  This will give you immediate feedback on errors and other log information, both on the server and client side.

If you did the above, your setup should look something like this:

Mobile First local dev setup for a Meteor app

Mobile First local dev setup for a Meteor app

You’ll also notice that I’ve toggled my device mode to be for a mobile device.  I highly recommend this, to ensure you are taking a Mobile First approach to implementing your app.

Add mobile meta tags (optional)

This step isn’t really specific to Meteor or React, but just good practice when building a web app.

You might have noticed that the text in the mobile device emulator is very tiny. Continuing with the “mobile first” approach, let’s make sure that your web app will look right when viewed in web browsers on mobile apps.

Replace the  <head>  block in your  /client/main.html with the following:

Here, we added mobile meta tags.  You’ll now notice that content in your browser is resized to a more “normal” size compared to the tiny size before.

Add React

Note: In a previous version of this blog post, I had included instructions to remove the package ‘blaze-html-templates’ Don’t remove it. Even though we are not using Blaze, this package serves additional functions, such as enabling use of plain html files.

Next, we are going to install React.  In contrast to when doing this for previous versions of Meteor, we’ll install React using npm.  One advantage of doing so is that we can ensure we are getting the most recent version of React. Another is that it gives us more control over which specific React packages we install.

Before continuing, you make sure you have installed Node.  (Technically speaking, you could complete the following steps without explicitly installing Node, since Meteor comes packaged with Node, but you’d likely be using an old version.)  Learn more about using npm with Meteor.

(Btw, do not confuse this with the similarly named package react-mount)

npm i react-mounter --save

Install React, ReactDOM, and react-mounter (the last package will be used by FlowRouter to handle React components.)

npm i react react-dom react-mounter --save

(If you were installing this using Meteor’s built-in version of node, you’d type  meteor npm install react react-dom react-mounter --save)

There’s a lot packed into that one command:

  • First, we are using the  i shorthand for install. (In other words, we could have typed  npm install ...)
  • Next, we are installing both the React package and the ReactDOM package. React is not specific to web apps, eg you can use React to create native iOS apps, so we therefore need a package for rendering to the DOM, which is the underlying structure of a web page.
  • Finally, we’re telling npm to update your local package.json file (which is your npm config file) with the names and versions of your installed packages or “dependencies.”  This has many advantages, including allowing you to not upload all the actual package files or “node_modules” files (which can become quite large) and instead just install everything using an npm install command.  Learn more about your package.json file. (On a related note, this is why you will almost always want to add “node_modules” to your  .gitignore file.  However, we didn’t need to do that, since Meteor has already done it for us.)

Why did we not add a placeholder for rendering React components?

If you have previously completed the Meteor React tutorial, you might expect that we’d at this point add a placeholder on our web page for react to render components, similar to these instructions.

However, in our case, we very explicitly do NOT want to do that, since this will be handled by FlowRouter.  (If you were to do this and also used FlowRouter, expect strange things to happen.)

Instead, let’s go ahead and install FlowRouter.

Add FlowRouter

FlowRouter is a popular routing package for Meteor app.  If you’ve used FlowRouter with React in a Meteor 1.2 app, you’ll notice that the install and setup process has changed somewhat for Meteor 1.3, when using React.

First, install the FlowRouter Meteor package:

meteor add kadira:flow-router

Why did we install this as a Meteor package and not using npm, you might ask?  Over time, more and more packages are likely to be installed using npm. However, the current version of FlowRouter is provided as a Meteor package.

(Btw, if you see a Meteor package name with a colon, this means it’s a community package.  The name before the colon is the name of the package creator, in this case Kadira.)

In your browser console, you should now see the following message:

FlowRouter dflt message: kadira_flow-router.js?hash=57de364…:509 There is no route for the path: /

FlowRouter default message: There is no route for the path: /

This means that, since our browser currently is pointed to “localhost:3000” which is the root path (which is the same as “/” in this context) for this local dev server, FlowRouter is looking for corresponding page to display but did not find one.

To create this root path, we need to do the following:

  1. Add a container component, into which a specific page can be rendered.
  2. Add a component that we’ll display when users navigate to the root (or homepage) view.
  3. Add a routes file, where we tell FlowRouter about the container and homepage components.

We will be placing all these files in the new “imports” directory, so let’s first talk a little about that.

The “imports” directory

If you have previous experience with Meteor, you might expect that we’d be adding a routes file in our client directory. (Anything placed inside a “client” directory will only be run on the client side.)

Now, while we could do that, we want more control over what gets loaded when our app starts up.  Therefore we are going to use the “imports” directory, which is a new “special” directory in Meteor 1.3

“Eager” vs “Lazy” Loading

By default, Meteor will load everything in your app directory on startup without you having to explicitly request that the files are loaded, aka “eager loading.”  While this can be a good thing, it can also become a problem, such as if you have a lot of files and you don’t actually need most of them just to start up the app.  That, in turn, might mean that the initial load of your app takes a long time to load, leaving users looking at an interminable “Loading” message…

Waiting and waiting for your app to load...

Waiting and waiting for your app to load…

Not a good thing :-/

With Meteor 1.3, you can add an “imports” directory, which allows you to do “lazy loading”, meaning that files in this directory are not loaded unless you specifically tell Meteor to load them (using “import” – more about that later), which can mean a faster app loading experience and also more control over file load order.

Ok, with that out of the way, let’s get started on the above steps by adding a a container component.

Add a layout component

Next, let’s create a component for defining our overall app layout.  Add the following file:

/imports/ui/layouts/app_layout.jsx

Note that we are placing this inside our imports directory. The use of the  ui directory is an emerging convention for where to place your components.

Note also the “jsx” file extension.  This means we’ll be using the JSX flavor of JavaScript, which is a common practice when using React.

This file doesn’t contain a lot of code but there is still a lot going on.  Let’s go through each part step by step.

Import/Export vs “magic” globals

What’s going in with this  import statement?  Here, we are importing the  React object from the  'react' npm package, which means we now can access all functionality supported inside that object (which is a lot.)

import and  export (see below) are part of the new ES2015 syntax. Don’t confuse this with the  “imports” directory we talked about earlier. You can use the  import statement most anywhere in your app, though it certainly is a good practice to place all the files you’ll want to import elsewhere in the “imports” directory.

The export statement

The  export statement is, as you might have guessed, the counterpart to the  import statement.  It is what makes whatever we export available via import elsewhere.

The stateless React component

While we are referring to  AppContainer as a React component, you might have noticed that we are not actually creating it using something like  React.createClass or  React.Component This is because, in React v0.14 and later, we can choose to use a plain JavaScript function to create a component.  Learn more about stateless React functions.

Es6 Arrow Functions

If you are new to ES6 syntax, this single-line function will likely look a bit odd to you:

If we were writing this function using the more familiar ES5 syntax, it would look like this:

(I replaced  const with  var to be ES5 compliant but that is a separate topic.)

Here, we are making use of several conveniences arrow functions provide.

  • Less typing: we create a lot of functions when writing JavaScript, so that is actually a big deal.
  • Implicit return: assuming we only have one statement block in our function, as is the case here, that statement block (the <div>...</div> ) becomes the function’s return value, ie we don’t have to use an explicit  return statement.
  • There is a lot more to arrow (or “fat arrow”) functions, including carried scope. Learn more here.

Passing a “content” prop into our component

Next, you’ll notice we are passing in  {content} as an argument into our function. This will be used by react-mounter to pass in the value (most likely a component) that has the same name (ie “content”) in our route. (Which we’ll add in a bit.)  The {...} syntax is part of the JSX syntax and means we are inserting a dynamic element into a JSX block.

Inserting “HTML” into a React component

If you are new to React, seeing what appears to be HTML inside (ie the <div>...</div>  part) a JavaScript statement might look odd. This, in fact, is not actual HTML, but just syntactic sugar provided by JSX that allows us to use HTML-like syntax in our JavaScript.  Why is this a good idea? Well, first, it means a lot fewer files to keep track of in our app (ie all HMTL template files get merged into our JS files.) But it also means re-thinking separation of concerns.  Learn more here.

Whoa, that was a lot packed into two lines of code!  Let’s keep going…

Add a Homepage Placeholder Component

Let’s add something to render on the homepage:

/imports/ui/pages/homepage.jsx

The usage of a  pages directory for your main views is also a somewhat emergent convention, to convey that these are the top-level components for your respective pages (or views), but you can place this file anywhere you wish inside the imports directory.

This file is mostly identical to the previous component we created, with one key difference: we are not passing in any props from the parent component, but we could easily update our component to do that.

Keep in mind: this is just a placeholder. You are likely to significantly update this component as you work on your app.

Add a Routes File

We now have everything we need to create a root route. Go ahead and create the following routes file:

/imports/startup/client/routes.jsx

This directory structure should be relatively self-explanatory: this is a file we will be loading on the client side at startup. (We’ll do the actual loading in a moment.)

Add the following code to this file:

Here, we are first loading the packages we need (ie  FlowRouterReact, and the  mount, method.)  Then, we are using import to load the two components we just created.  The part following the  from block is the path to that file.  Note that you can omit the file extension in these paths.

Why I avoid using ‘export default’

One little detail here is in the import syntax.  Note the use of  {AppContainer} What this is saying is that we are importing something called “AppContainer” from within the file that we referenced.  You may sometimes see syntax like  export default ... What this means is that you can now import the equivalent element by omitting the curly braces.  In other words, you would have been able to write  import AppContainer from ....  I recommend avoiding using default. Why?  Because this means that when are importing something you have to try to remember if you used default and if you should enclose the item in curly braces or not.  If you know that you don’t use  default, it will be one less item to think about.

Creating the Route

Next, we have the code for creating the actual route.  Most of what is going on here is very well documented in the FlowRouter guide.  However, the only key difference is that you are using the mount() method rather than React Layout for rendering your component.

Also, note the the content param inside this method. This is what corresponds to the  {content} param in the AppContainer we created earlier.

I created my routes file. Why doesn’t my page show up?

After adding this file, you might expect to see your new route displayed, but instead nothing happens.  We added our route, why is it not showing up?

This is because we’ve placed our file inside the “imports” directory and, as you might recall, those files are not loaded unless we specifically request them.  Let’s do that next.

Load our Routes on Startup

We now need to add a files in our clients directory (which is “eagerly” loaded by Meteor) that imports the files we’ve created.

Create an Import Index File

This step isn’t actually necessary, but it will make for more organized code in the long run.  Create the following file:

/imports/startup/client/index.js

In case you are wondering, the  ./ part means “the current directory.”  In other words, if you want to import something that is in the same directory, you have to always append this at the beginning.

In this file, we are basically creating a manifest for all the files that will be loaded on startup into the client.  For now,  we are just loading a single file, but as our app grows, so will this list, and it will offer both an overview of everything being loaded and allow us to control load order.

Add the import instruction to main.js

Go ahead and update the following file (that was created by default by Meteor):

/client/main.js

Since   client here is a directory and we are not specifying a file inside that directory, the import will look for the  index file we created. This means we will not need to touch this file when making changes to what is imported on startup, but instead only need to update the index file being referenced.

We now only have three files in our client directory, which just looks clean, if nothing else.

Client directory with three main files

Client directory with three main files

More importantly, we are only loading what we need on startup and nothing more.

Your browser should now look like this:

Homepage successfully added to a Meteor app using FlowRouter

Homepage successfully added to a Meteor app using FlowRouter

Not very exciting, I know :}  But quite useful.

Why no semi-colons?

One more thing.  You might have noticed that I don’t use semi-colons in my JavaScript.  The short reason for this is that semi-colons actually aren’t needed in most cases (in some cases, they are necessary.) Any characters you can remove from your code means less noise and more readable code.  Learn more here.   Whether or not to use semi-colons is up to you.

Keep Going: Add data to your React components

Next, learn about how to use reactive data sources with your React components.

I hope you found this useful.  If you liked it, please let me know in the comments and/or tweet about it. Also, if you found any errors, definitely let me know in the comments.

23 Comments

  1. I hadn’t been able to use FlowRouter but with this tutorial I could. Thank you for the step-by-step explanation

  2. Thank a lot
    I don’t understand before. but when i read your content and make me understand the Meteor, React and Flow-router.

  3. How relevant is this article as of July 2016? Meteor seems to be a moving target as of late.

    Thanks!

  4. Silly Questions,
    In routes.jsx, we import everything like React, {mount}, etc. but we never import FlowRouter ?

  5. I think you are using App, AppLayout and AppContainer interchangeably in the code above. But it’s a good read to begin things off :) .

    Thanks.

    • Looks like there were a couple places where I referred to App when I should have referred to AppLayout. All fixed now. Thanks for pointing it out.

  6. Great article!
    So much better then the tutorial of Meteor itself.
    What makes me a bit dubitate about meteor is the circumstance, that so important packages like the router and mount packages of kadira are not initially a part of meteor.
    I think it makes many people very confusing (like me..)
    Best regards

  7. Nice writeup – first I have seen that actually uses the imports folder. However I think something is still incorrect. We create a layout in /imports/ui/layouts/app.jsx – but then all the code following that references AppContainer in ../../ui/containers/app_container.

    I know in the next section we’ll use both – but if we need to create both now you should say so here. If not then we cannot create one and import another without first creating and importing the first into the second.

  8. There is still text that refers to AppContainer, while in the code it is now Main_Layout

      • Hi, Very nice tutorial, Thanks.
        I Guess there is stil some typo pb

        the code says
        export const App = ({content}) => {content}
        but, it should be AppContainer instead of App

        Also,
        import {AppContainer} from ‘../../ui/containers/app_container’
        should be
        import {AppContainer} from ‘../../ui/containers/app’
        since we named the file app.jsx

        Then every thing works well…. as is clearly explained … THANKS
        Moving to next tuto

        • Hi Wassim – thanks for your comments. Actually, the way I have it is correct. As you will see, when continuing to the next part in this tutorial, we have both an App layout and AppContainer, used for data.

          I apologize for the confusion. Next time, I’ll separate this out into different branches or repos.

  9. Thank you for writing this. Its very useful for a beginner..

  10. Thanks very much for this excellent article. The line-by-line walkthrough is just what I needed.

Comments are closed.

Webmentions

  • Build a Simple Note-taking App with Meteor and React – Coder Chronicles April 9, 2016

    Thanks very much for this excellent article. The line-by-line walkthrough is just what I needed.

  • Using Data in Meteor with React and FlowRouter – Coder Chronicles April 9, 2016

    Thanks very much for this excellent article. The line-by-line walkthrough is just what I needed.