Skip to content

Latest commit

 

History

History
165 lines (113 loc) · 5.84 KB

FRAMEWORK-SPECIFIC.md

File metadata and controls

165 lines (113 loc) · 5.84 KB

React

Component Design

Follow the Low of Demeter: keep component props flat. Don't make your components reach deep into nested objects to get the data it needs to render. This couples your view code with your underlying data structure. Components should have clear contracts, requiring only the minimal amount of information it needs to do its job.

Code Example:

Bad This component has way to much knowledge about how we store user objects!

// UserBadge.jsx
import React from 'react';

export default ({ user }) => (
  <div>
    <img src={user.avatar.imagePathLarge} alt="User image" />
    <span>Hello {user.firstName}!</span>
  </div>
);

Good

// UserBadge.jsx
import React from 'react';

export default ({ avatarImagePath, displayName }) => (
  <div>
    <img src={avatarImagePath} alt="User image" />
    <span>Hello {displayName}!</span>
  </div>
);

Terms

HOC - Higher-order component Component decorator PFC - Pure functional component

Testing

General Tips

  • Prefer shallow rendering - This speeds up your tests and prevents you from writing redundant tests

Testing Components

  • Use factories (See Testing section for general rationale)
  • Only test public API (rendered elements, action handlers)
  • Assert collaborator components are given proper props
  • [TODO: Add examples]

Testing Higher-Order-Components (HOCs)

[TODO]

Testing Containers

[TODO]

Sharing Code/State

Higher-Order-Component (HOC)

[TODO]

Render prop pattern

[TODO]

** Gotchas **

SICK AWESOME DOPE COMPARISON SHOWING WHICH USAGE PATTERNS CAUSE EXTRA RENDERS: https://codepen.io/danny-andrews/pen/LzyRvO.

[TODO: Add example pen]

Performance

Optimize component rendering

By default, React components (class and functional) always re-render, even if the props passed in are identical to those previously given. Sometimes this ends up being faster, since you don't have the overhead of comparing props on every render, but for components on hot code paths (or high in the tree) this can negatively impact performance [TODO: Add link to real-world benchmark demonstrating this]. Luckily, there are workarounds.

  • For class methods, inherit from PureComponent - This defines a shouldComponentUpdate hook which shallowly compares props and state (so don't be mutating those!)

  • For PFCs, you can either use recompose#pure or this little snippet:

    function pure(func) {
      class PureComponentWrap extends React.PureComponent {
        render() {
          return func(this.props, this.context)
        }
      }
      return PureComponentWrap
    }

Avoid using bind or inlining function definitions in render *

Both of these patterns result in a new function being created each time a component. This results in

  1. Extraneous garbage collection invocations which can slow performance [TODO: Add link to real-world benchmark demonstrating this]
  2. Extra re-renders in components which define shouldComponentUpdate.

[TODO: Add Good and Bad examples]

[TODO: Add section describing workarounds for both class and functional components]

Organization

  • Directory structure

+ Redux

  • Separate components from containers

Crisp Reading:

CSS

Npm

Modern Packaging

http://2ality.com/2017/04/setting-up-multi-platform-packages.html#main-native-features-cjs https://github.com/rollup/rollup/wiki/pkg.module

package.json schema

  • Always write three digits (e.g. don’t do 1.0)
  • Prefer ~ and ^ to any other types of ranges
  • If you need a more complex range, prefer the - syntax
  • If you need an X-Range, use x as the character, not X

JavaScript

Object Creation Pattern

Douglas Crockford recommends a pattern for creating objects in a functional way. The basic idea is to have a factory function which acts as a constructor. Now new. No class. No inheritance. But easy composition/mixin potential. This pattern allows for true private members. I dub this pattern "Crock-Pot" patterns, because you but good things in, and get something better out! And you freeze it for later! Example:

const Reader = value => {
  const run = config => value(config);
  const map = fn => Reader(config => fn(run(config)));
  const chain = fn => Reader(config => fn(run(config)).run(config));

  return Object.freeze({ map, chain });
}