Skip to content
Joss Mackison edited this page May 18, 2016 · 3 revisions

Home > Knowledge Base > Coding Standards

Table of Contents

  1. Testing and Documentation
  2. Coding Standards - Indentation - Objects - Strings - Closure References to this
  3. Admin UI Front-end - Syntax

Testing and Documentation

We are currently improving documentation and test coverage for Keystone, any help with this would be greatly appreciated.

Any additions or changes to functionality that has been documented should be accompanied by updates to the docs; these can be found in /docs/content/pages. You can preview the http://keystonejs.com website locally by running node docs from within the /docs folder. Actual build and publishing of the website to the gh-pages branch is managed by @JedWatson.

Before submitting a PR, please ensure the current test suite passes by running gulp test.

Back to top

Coding Standards

Please see the editor and eslint settings for specific details:

Generally, you should follow these guidelines:

Indentation

KeystoneJS uses tabs for indentation except in JSON, where 2 spaces should be used.

Objects

Reserved words should generally be avoided as object property keys, except where required by Mongoose (e.g. the default option for Schema paths).

Property keys should not be quoted unless they are invalid syntax; the same goes for using object notation to access properties. For example:

var obj = { x: 1 };
console.log(obj.x);

var obj = { 'some-property': 1 };
console.log(obj['some-property']);

Strings

Generally use single quotes. Double quotes may be used if it has a significantly positive impact on code readability (e.g. excessive escaping of single quotes required).

Strings longer than 80 characters should be written across multiple lines using string concatenation, unless using longer strings has a significantly positive impact on code readability.

Closure References to this

Use .bind(this) to avoid closure references to this when it makes code more readable (small blocks).

When it's clearer to create a closure reference (e.g. larger blocks of code, or more than one level of binding required) use either self or a descriptive variable name (e.g. field) when self could be misinterpreted.

Back to top

Admin UI Front-end

Syntax

Order your methods with lifecycle first and render last.

Within your react component, you should order your methods like so:

  1. lifecycle methods (in chronological order):
staticMethod ()
constructor ()
componentWillMount ()
componentDidMount ()
componentWillReceiveProps ()
shouldComponentUpdate ()
componentWillUpdate ()
componentDidUpdate ()
componentWillUnmount ()
  1. everything else
  2. render

Name handlers handleEventName.

Example:

<Component onClick={this.handleClick} onLaunchMissiles={this.handleLaunchMissiles} />

Name handlers in props onEventName.

This is consistent with React's event naming: onClick, onDrag, onChange, etc.

Example:

<Component onLaunchMissiles={this.handleLaunchMissiles} />

Open multiline elements inside parentheses

Elements that span more than 80 characters or contain multiple nodes should open on a separate line.

Yes:

return (
  <div>
    <div>
      ...
    </div>
  </div>
);

Yes:

return <div>...</div>;

No:

return <div>  // "div" is on the same line as "return"
  <div>
    ...
  </div>
</div>;

Align and sort HTML properties.

Fit them all on the same line if you can (80 characters). If you can't, put each property on a line of its own, indented, in sorted order. The closing angle brace should be on a line of its own, indented the same as the opening angle brace. This makes it easy to see the props at a glance.

Yes:

<div className="highlight" key="highlight-div">
<div
  className="highlight"
  key="highlight-div"
>
<Image
  className="highlight"
  key="highlight-div"
/>

No:

<div className="highlight"      // property not on its own line
  key="highlight-div"
>
<div                            // closing brace not on its own line
  className="highlight"
  key="highlight-div">
<div                            // property is not sorted
  key="highlight-div"
  className="highlight"
>

Only export a single react class.

Every .jsx file should export a single react class, and nothing else. This is for testability: fixture frameworks requires it to function.

Note: The file can still define multiple classes, it just can't export more than one.

Back to top

Language features

Make "presentation" components pure.

It's useful to think of the React world as divided into "logic" components and "presentation" components.

  • "Logic" components have application logic, but do not emit HTML themselves.
  • "Presentation" components are typically reusable, and do emit HTML.

Logic components can have internal state, but presentation components never should. Prefer stateless functional components unless a shouldComponentUpdate() method is required.

You almost always want to use props. By avoiding state when possible, you minimize redundancy, making it easier to reason about your application.

A common pattern -- which matches the "logic" vs. "presentation" component distinction -- is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via props. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.

Copying data from props to state ​can cause the UI to get out of sync and is especially bad.

React Components should always have complete propTypes declared. Every attribute of this.props should have a corresponding entry in propTypes. This makes it easier for a developer unfamiliar with the component to understand it's scope and intention.

Avoid these non-descriptive prop-types:

  • React.PropTypes.any
  • React.PropTypes.array
  • React.PropTypes.object

Instead, use

  • React.PropTypes.arrayOf
  • React.PropTypes.objectOf
  • React.PropTypes.instanceOf
  • React.PropTypes.shape

Never store state in the DOM.

Do not use data- attributes or classes. All information should be stored in Javascript.

Back to top