Skip to content

Latest commit

 

History

History
199 lines (155 loc) · 4.37 KB

react-style-guide.md

File metadata and controls

199 lines (155 loc) · 4.37 KB

React Style Guide

Folder Structure

  • Place each component in a separate folder
  • Avoid having shared resources between components (css, images etc.)
  • Keep all components' folders in the same parent folder (avoid nesting)
File structure per component example:
/src/components/Navigation/icon.svg
/src/components/Navigation/Navigation.js
/src/components/Navigation/Navigation.less
/src/components/Navigation/Navigation.test.js
/src/components/Navigation/Navigation.ru-RU.less
/src/components/Navigation/package.json

For more information google for component-based UI development.

CSS Class Names

Use BEM approach for naming CSS classes. See also SUIT CSS for inspiration.

// CSS
.ComponentName { }
.ComponentName--modifier { }
.ComponentName-elementName { }
.ComponentName-elementName--modifier { }
CSS styling example:
// JSX
<nav className="Navigation">
  <ul className="Navigation-items">
    <li className="Navigation-item Navigation-item--selected">
      <a className="Navigation-link" href="/products">Products</a>
    </li>
    <li className="Navigation-item">
      <a className="Navigation-link" href="/services">Services</a>
    </li>
  </ul>
</nav>
// LESS
.Navigation {
  &-items {
    margin: 0;
    padding: 0;
    list-style-type: none;
    text-align: center;
  }

  &-item {
    display: inline-block;
    vertical-align: top;
  }

  &-link {
    display: block;
    padding: 0 25px;
    outline: 0;
    border: 0;
    color: @default-color;
    text-decoration: none;
    line-height: 25px;
    transition: background-color .3s ease;

    &,
    .Navigation-items:hover & {
      background: @default-bg-color;
    }

    &--selected,
    .Navigation-items:hover &:hover {
      background: @active-bg-color;
    }
  }
}

React Components

  • Use Babel transpiler for your source code
  • Use ES6 classes for creating new React components
  • Use higher-order components to extend the functionality of existing components
React component example:
import './SampleComponent.less';
import React, { Component } from 'react';

class SampleComponent extends Component {

  static propTypes = { ... };

  static defaultProps = { ... };
  
  constructor() {
    super();
    this.state = { ... };
  }

  componentDidMount() {
    // ...
  }

  componentWillUnmount() {
    // ...
  }

  shouldComponentUpdate() {
    // ...
  }

  render() {
    return (
      <div className="SampleComponent">
      </div>
    );
  }

}

export default SampleComponent;

Put custom methods and properties at the bottom of the file, after the render() method.

Higher-order React component example:
// setViewport.js
import React, { Component } from 'react';
import { canUseDOM } from 'react/lib/ExecutionEnvironment';

function setViewport(ComposedComponent) {
  return class Viewport extends Component {

    constructor() {
      super();

      this.state = {
        viewport: canUseDOM ?
          {width: window.innerWidth, height: window.innerHeight} :
          {width: 1366, height: 768} // Default size for server-side rendering
      };

      this.handleResize = () => {
        let viewport = {width: window.innerWidth, height: window.innerHeight};
        if (this.state.viewport.width !== viewport.width ||
          this.state.viewport.height !== viewport.height) {
          this.setState({viewport: viewport});
        }
      };
    }

    componentDidMount() {
      window.addEventListener('resize', this.handleResize);
      window.addEventListener('orientationchange', this.handleResize);
    }

    componentWillUnmount() {
      window.removeEventListener('resize', this.handleResize);
      window.removeEventListener('orientationchange', this.handleResize);
    }

    render() {
      return <ComposedComponent {...this.props} viewport={this.state.viewport}/>;
    }

  };
};

export default setViewport;
// MyComponent.js
import React from 'react';
import setViewport from './setViewport';

@setViewport
class MyComponent {
  render() {
    let { width, height } = this.props.viewport;
    return <div>{'Viewport: ' + width + 'x' + height}</div>;
  }
}

export default MyComponent;