As a community, Reaction follows guidelines for code style and naming conventions for variables, methods and filenames. The guide also includes tips on working with libraries in Reaction, like React, MongoDB, lodash and more.
- Syntax and style conventions
- Naming conventions
- Working with packages
- JavaScript style recommendations
- Copy conventions
Our rules are similar to Airbnb JavaScript Style Guide and Meteor Code Style, standard template of ESLint rules, with a few custom Reaction-specific rules:
-
Always double-quote strings
-
Give methods space
-
Add spaces around brackets
-
120 character line-length
-
import
s should be listed in this order, as enforced by ESLint:-
Built-in: Built-in Node modules
-
External: External packages, ordered by:
- React packages
- External npm modules
- Meteor Core packages
- Meteor Atmosphere packages
-
Internal: Internal Reaction modules
-
Parent: Modules from a parent directory
-
Sibling: Modules from the same or sibling directories
-
Index: Index of the current directory
-
Other Reaction-specific rules are checked using various linting libraries. Find all the rules in the code:
.eslintrc
- ESLint checks JavaScript style, including ES2015, React and Babel..jsbeautifyrc
- JS Beautifier automates code formatting.editorconfig
- Editor Config standardizes file formatting
To see the rules in action, run eslint .
from the command line or use ESLint code editor tools.
💡 ProTip! If you're using Atom, like the Core team, you can install all the necessary tools in one line: apm install editorconfig atom-beautify linter linter-eslint linter-markdown linter-jsonlint linter-docker
File and directory names should be hyphenated. Not all operating systems are case sensitive, so avoid having two files named the same with differing case.
Names of folders and files should be:
- Lowercased
- Alphanumeric characters
- Hyphenated to join more words
- Avoid
camelCase
,undescore_casing
- Files may use multiple
.
as needed
Do
/ui-grid/
/example-payment-method/
/social/
/bootstrap.rtl.js
/index.js
Don't
/reactionpackagename/
/address_book/
/addressBook/
/settingsContainer.js
/addressBook.js
/address_book.js
Namespace package folders in this format: <functionality>-<package-name>
or <organization-name>-<package-name>
/imports/plugins/custom/payments-authnet
/imports/plugins/included/connectors-shopify
/imports/plugins/custom/connectors-magento
/reaction-paypal/
/yourorg-your-package/
If there are multiple files that provide functionality that is broken down across multiple files, these files should be grouped within a folder.
If the files are stand-alone and the name needs to represent functionality, you can use a hyphen for the separator.
Do
/container/settings.js
/container/settings.html
/container/ <more files>
// or
/settings-container.js
/settings-container.html
Don't
/container/settings-containers.js
/container/settingsContainer.html
settingsContainer.js
Variable names should be:
- Meaningful. Avoid single-letter variables.
- Use
error
, instead ofe
orerr
- Variables that contain a boolean value should use a
isThisTrue
style. - Variables that return arrays should be plural.
Publication names should:
- Use TitleCase
Working with variables:
- Use
const
except when a variable is being reassigned. - Use string template notation,
${thisVariable} is true
over string concatenation
Naming methods:
- Methods names should use a verb/noun style when possible, e.g.
checkConfiguration
oraddToCart
. - When naming multiple methods acting on the same resource should follow this style, e.g.
cart/items/add
,cart/items/remove
- Methods that return a single value should be singular.
- Methods whose main purpose is to return a value should use the
get
prefix, e.g.getShop
.
Working with methods:
- Avoid ternary operators and one-line
if
statements (except in React componenets) - Use parenthesis around all method arguments:
// do - use () around the method arguments
cartItems.find((item) => item.status === picked)
// don't
cartItems.find(item => item.status === picked)
- When specifying a callback, always use the parenthesis to indicate the argument being accepted over the bare arrow-function form. This way, it's clear it's not another argument to the original function:
// do - explicitly use a () in the callback function
thisMethodTakesACallback(arg1, arg2, (result) => {
dostuff();
});
// don't
thisMethodTakesACallback(arg1, arg2, result => {
doStuff
});
- When breaking arrow functions into multiple lines, use curly brackets and a
return
:
// do - explicitly use a return
cartItems.find((item) => {
return item.status === status;
})
// don't
cartItems.find(
(item) => item.status === status
)
- Be explicit in querying:
// do - explicitly state the key being queried
Products.findOne({ _id: "abc123" })
// don't
Products.findOne("abc123")
Use native JavaScript over libraries like lodash and Underscore whenever there is a suitable replacement.
- Replace
_.map
, withArray.prototype.map
- Replace
_.reduce
, withArray.prototype.reduce
- Replace
_.filter
, withArray.prototype.filter
- Replace
_.isArray
, withArray.isArray
- Replace
_.extend
withObject.assign
- Replace
_.find
withArray.prototype.find
- Replace
_.keys
and_.values
, withObject.keys
andObject.values
- Replace
_.first
,_.rest
and_.restParam
, with destructuring syntax - Replace
_.uniq
, with using aSet
:[...new Set(cartItems.map((item) => item.product._id))]
- Replace
pluck
from Underscore with.map
:
const people = [{name: "George"}, {name: "Katherine"}, {name: "Kip"}]
_.pluck(people, name) => people.map((person) => person.name)
- Replace
_.each
,_.forEach
, withArray.prototype.forEach
or loop over an object with:
sum = 0;
lastKey = undefined;
for (const [key, value] of Object.entries(foo)) {
sum += value;
lastKey = key;
}
- Use
isRequired
for validating PropTypes - Use the return shorthand with arrow functions in React components:
// do
const MyComponent = ({ title, content }) => (
<div>
<h1>{title}</h1>
<div>{content}/</div>
</div>
);
// don't
const MyComponent = ({ title, content }) => {
return (
<div>
<h1>{title}</h1>
<div>{content}/</div>
</div>
);
}
- Use the return shorthand with arrow function when iterating over arrays in a component:
const MyThings = ({ things }) => (
<ul>
{things.map((thing) => <li>{thing}</li>)}
</ul>
);
// or
const MyThings = ({ things }) => (
<ul>
{things.map((thing) => (
<li>{thing}</li>
))}
</ul>
);
When writing user interface copy for Reaction, use sentence casing. This includes copy for titles, buttons, alerts, form inputs, form placeholders and copy elsewhere used throughout the application.
Copy should be:
- Have the first letter capitalized.
- No other words should be capitalized.
- Example:
Your orders
instead ofYour Orders
// do
<h3 class="panel-title">Your orders</h3>
<Components.Translation defaultValue="Payment method" i18nKey={"cartCompleted.paymentMethod"} />
// don't
<h3 class="panel-title">Your Orders</h3>
<Components.Translation defaultValue="Payment Method" i18nKey={"cartCompleted.paymentMethod"} />