Skip to content

Skeletal example app showing how to integrate Meteor and React with some basic user management

Notifications You must be signed in to change notification settings

optilude/meteor-react-example

Repository files navigation

Meteor/React Example

This package contains an example app that uses Meteor and React together. It demonstrates:

  • Using the react package to integrate Meteor and React
  • Fetching data from reactive Meteor data sources using the ReactMeteorData mixin and the getMeteorData() method
  • Routing using ReactRouter
  • A basic UI using Twitter Bootstrap and ReactBootstrap
  • Login, change password, enrollment emails and user management using the Meteor accounts system
  • ES6 syntax using the Babel transpiler (.import.js files) and ReactJS' transpiler (.jsx files)
  • ES6 modules using universe:modules
  • Tests using Velocity.
  • Typed collections / validation using aldeed:collection2.
  • Client- and server-side dependencies loaded from NPM and served with browserify.
  • JSHint configuration to allow editors like Sublime Text or Atom to warn about potential problems early

The app is very simple: it shows a ticking clock and allows the user to record a timestamp with a name. Most of the sample app-specific logic can be found in client/components/timestamps.import.jsx and lib/models.import.js, with references from client/components/app.import.jsx, client/components/navigation.import.jsx, client/js/routing.import.jsx and client/css/example.css.

The various files have comments explaining their purpose and logic. At a high level:

  • client/ contains various React UI components and other client-side-only code. Most of these are relatively re-usable, for example the login, change password, enrollment and user management components.
  • server/ contains server-only functionality such as application initialisation and methods.
  • lib/ contains shared code such as model/collection definitions and publications.
  • tests/ contains Velocity tests using the Jasmine test syntax. The tests there are examples generated by Velocity and pretty frivolous. The test runner can be found in the top right hand corner of the running app.

Approach to dependencies and modularisation

Meteor does not (yet!) have a good approach to modularising applications. In short, all of the JavaScript code intended for the client is loaded into the browser as <script /> tags, and so it is easy to end up with load-order problems. Meteor does have a packaging system that supports dependency management and imports, but it is quite ideosyncratic and requires that any library found on e.g. NPMJS is wrapped into a Meteor package.

In this example, we have taken the following approach:

  • We have created a "private" package called packages/app-deps (using meteor create --package).

  • In the package.js file, we declare dependencies on published NPM modules using the standard Meteor API for this. When the package is built, this will cause Meteor to download the relevant modules.

  • We use the cosmos:browserify package to run Browserify when the package is built to create a bundle that can be sent to the client. In the file client.browserify.js (plus some relevant options in client.browserify.options.json), we require the relevant modules and put them into a global object called Dependencies. We do something similar for server-side dependencies in server.js in the package.

  • Dependencies are then exported using magic provided by universe:modules. The main.export.jsx file declares the exports, and the system-config.js file allows imports like:

    import { _, Router } from 'app-deps';
    

We also use universe:modules to allow ES6 module syntax in app code. Almost all app-specific files are named with .import.jsx or .import.js syntax. Within these files, we can use syntax like:

import Loading from 'client/components/loading';

In loading.import.jsx, we have:

/* jshint esnext:true */
/* global Meteor, React */

"use strict";

import { _, ReactBootstrap } from 'app-deps';

var { Modal, ProgressBar } = ReactBootstrap;

export default React.createClass({
    displayName: 'Loading',

    render: function() {
        return (
            <div className="please-wait modal-open">
                <Modal
                    title='Please wait...'
                    backdrop={false}
                    animation={false}
                    closeButton={false}
                    onRequestHide={() => {}}>
                    <div className='modal-body'>
                        <ProgressBar active now={100} />
                    </div>
                </Modal>
            </div>
        );
    }

});

To kick it all off, we have client/main.js:

/* jshint: esnext: true */
/* global System */
"use strict";

System.import('client/routing');

This loads client/routing.import.jsx, from which all other components are imported.

Similarly, for server-side code, we have server/main.js:

/* jshint: esnext: true */
/* global System */
"use strict";

System.import('server/startup');

And at the top of server/startup.import.js:

import 'lib/models';
import 'server/admin';

This ensures that "global" code in these modules is run on startup.

About

Skeletal example app showing how to integrate Meteor and React with some basic user management

Resources

Stars

Watchers

Forks

Packages

No packages published