Skip to content

Latest commit

 

History

History
503 lines (410 loc) · 14.5 KB

README.md

File metadata and controls

503 lines (410 loc) · 14.5 KB

Правила оформления кода на React

React является JavaScript-библиотекой, поэтому помимо нижеизложенных, следует также придерживаться правил оформления JavaScript кода.

  1. Создание компонента без внутреннего состояния и ссылок
  2. Именование
    2.1. Расширения
    2.2. Имя файла
    2.3. Именование переменной
    2.4. Именование компонента
    2.5. Именование компонента высшего порядка
    2.6. Названия свойств
  3. Выравнивание
  4. Кавычки
  5. Пробелы
  6. Свойства (Props)
    6.1. Названия свойств
    6.2. Значения свойств
    6.3. Свойство key
    6.4. defaultProps
  7. Круглые скобки
  8. Теги
  9. Методы
    9.1. Замыкание локальных переменных
    9.2. Привязка обработчиков событий
    9.3. Возврат значений в render
  10. Последовательность
    10.1. Последовательность вызова методов внутри компонента
    10.2. Как определять propTypes, defaultProps, contextTypes, и т.д.
    10.3. isMounted

1. Создание компонента без внутреннего состояния и ссылок

Если у компонента нет состояния (state) или ссылок (refs), используйте функции, а не классы.

Хорошо

function Listing({ hello }) {
  return <div>{hello}</div>;
}

Хорошо

const Listing = ({ hello }) => (
  <div>{hello}</div>
);

Плохо

class Listing extends React.Component {
  render() {
    return <div>{this.props.hello}</div>;
  }
}

2. Именование

2.1 Расширения

Используйте расширение .js для компонентов React.

2.2 Имя файла

Используйте PascalCase для названий файлов, например, ReservationCard.js.

2.3 Именование переменной

Используйте PascalCase для компонентов React.

Хорошо

import ReservationCard from './ReservationCard';

Плохо

import reservationCard from './ReservationCard';

Используйте camelCase для экземпляров компонентов React.

Хорошо

const reservationItem = <ReservationCard />;

Плохо

const ReservationItem = <ReservationCard />;

2.4 Именование компонента

Называйте файлы так же как и компоненты. Например, ReservationCard.js должен содержать внутри компонент ReservationCard. Однако корневые компоненты в директории должны лежать в файле index.js, и в этом случае название папки должно быть таким же, как название компонента.

Хорошо

import Footer from './Footer';

Плохо

import Footer from './Footer/Footer';

Плохо

import Footer from './Footer/index';

2.5 Именование компонента высшего порядка

Используйте сочетание имени компонента высшего порядка и имени переданного в него компонента как свойство displayName сгенерированного компонента. Например, из компонента высшего порядка withFoo(), которому передан компонент Bar, должен получаться компонент с displayName равным withFoo(Bar).

Почему? Свойство displayName может использоваться в инструментах разработчика или сообщениях об ошибках, и если оно ясно выражает связь между компонентами, это помогает понять, что происходит.

Хорошо

export default function withFoo(WrappedComponent) {
  function WithFoo(props) {
    return <WrappedComponent {...props} foo />;
  }

  const wrappedComponentName = WrappedComponent.displayName
    || WrappedComponent.name
    || 'Component';

  WithFoo.displayName = `withFoo(${wrappedComponentName})`;
  return WithFoo;
}

Плохо

export default function withFoo(WrappedComponent) {
  return function WithFoo(props) {
    return <WrappedComponent {...props} foo />;
  }
}

2.6 Названия свойств

Избегайте использования названий свойств DOM-компонента для других целей.

Почему? Люди ожидают, что такие свойства как style и className имеют одно определенное значение. Изменение этого API в вашем приложении ухудшает читабельность и поддержку кода, что может приводить к ошибкам.

Хорошо

<MyComponent variant="fancy" />

Плохо

<MyComponent style="fancy" />

3. Выравнивание

Следуйте приведенным ниже стилям для JSX-синтаксиса.

Хорошо

<Foo
  superLongParam="bar"
  anotherSuperLongParam="baz"
/>

Плохо

<Foo superLongParam="bar"
     anotherSuperLongParam="baz" />

Если свойства помещаются на одну строку, оставляйте их на одной строке.

<Foo bar="bar" />

Отступ у дочерних элементов задается как обычно.

<Foo
  superLongParam="bar"
  anotherSuperLongParam="baz"
>
  <Quux />
</Foo>

4. Кавычки

Всегда используйте двойные кавычки: (") для JSX-атрибутов.

Хорошо

<Foo bar="bar" userName="hello" />

Плохо

<Foo bar='bar' userName='hello' />

Плохо

<Foo bar='bar' userName="hello" />

5. Пробелы

Не отделяйте фигурные скобки пробелами в JSX.

Хорошо

<Foo bar={baz} />

Плохо

<Foo bar={ baz } />

6. Свойства (Props)

6.1 Названия свойств

Всегда используйте camelCase для названий свойств.

Хорошо

<Foo
  userName="hello"
  phoneNumber={12345678}
/>

Плохо

<Foo
  UserName="hello"
  phone_number={12345678}
/>

6.2 Значения свойств

Не указывайте значение свойства, когда оно явно true.

Хорошо

<Foo
  hidden
/>

Плохо

<Foo
  hidden={true}
/>

6.3 Свойство key

Не используйте индексы элементов массива в качестве свойства key. Отдавайте предпочтение уникальному ID.

Хорошо

{todos.map(todo => (
  <Todo
    {...todo}
    key={todo.id}
  />
))}

Плохо

{todos.map((todo, index) =>
  <Todo
    {...todo}
    key={index}
  />
)}

6.4 defaultProps

Всегда указывайте явные defaultProps для всех свойств, которые не указаны как необходимые.

Почему? propTypes является способом документации, а предоставление defaultProps позволяет читателю вашего кода избежать множества неясностей. Кроме того, это может означать, что ваш код может пропустить определенные проверки типов.

Хорошо

function SFC({ foo, bar, children }) {
  return <div>{foo}{bar}{children}</div>;
}
SFC.propTypes = {
  foo: PropTypes.number.isRequired,
  bar: PropTypes.string,
  children: PropTypes.node,
};
SFC.defaultProps = {
  bar: '',
  children: null,
};

Плохо

function SFC({ foo, bar, children }) {
  return <div>{foo}{bar}{children}</div>;
}
SFC.propTypes = {
  foo: PropTypes.number.isRequired,
  bar: PropTypes.string,
  children: PropTypes.node,
};

7. Круглые скобки

Оборачивайте в скобки JSX теги, когда они занимают больше одной строки.

Хорошо

render() {
  return (
    <MyComponent className="long body" foo="bar">
      <MyChild />
    </MyComponent>
  );
}

Хорошо, когда одна строка

render() {
  const body = <div>hello</div>;
  return <MyComponent>{body}</MyComponent>;
}

Плохо

render() {
  return <MyComponent className="long body" foo="bar">
           <MyChild />
         </MyComponent>;
}

8. Теги

Всегда используйте самозакрывающиеся теги, если у элемента нет дочерних элементов.

Хорошо

<Foo className="stuff" />

Плохо

<Foo className="stuff"></Foo>

Если ваш компонент имеет множество свойств, которые располагаются на нескольких строчках, то закрывайте тег на новой строке.

Хорошо

<Foo
  bar="bar"
  baz="baz"
/>

Плохо

<Foo
  bar="bar"
  baz="baz" />

9. Методы

9.1 Замыкание локальных переменных

Используйте стрелочные функции для замыкания локальных переменных.

Хорошо

function ItemList(props) {
  return (
    <ul>
      {props.items.map((item, index) => (
        <Item
          key={item.key}
          onClick={() => doSomethingWith(item.name, index)}
        />
      ))}
    </ul>
  );
}

9.2 Привязка обработчиков событий

Привязывайте обработчики событий для метода render в конструкторе.

Почему? Вызов bind в методе render создает новую функцию при каждой перерисовке.

Хорошо

class extends React.Component {
  constructor(props) {
    super(props);

    this.onClickDiv = this.onClickDiv.bind(this);
  }

  onClickDiv() {
    // ...
  }

  render() {
    return <div onClick={this.onClickDiv} />;
  }
}

Плохо

class extends React.Component {
  onClickDiv() {
    // ...
  }

  render() {
    return <div onClick={this.onClickDiv.bind(this)} />;
  }
}

9.3 Возврат значений в render

Всегда возвращайте значение в методах render.

Хорошо

render() {
  return (<div />);
}

Плохо

render() {
  (<div />);
}

10. Последовательность

10.1 Последовательность вызова методов внутри компонента

Последовательность для class extends React.Component:

  1. произвольные static методы;
  2. constructor;
  3. getChildContext;
  4. componentWillMount;
  5. componentDidMount;
  6. componentWillReceiveProps;
  7. shouldComponentUpdate;
  8. componentWillUpdate;
  9. componentDidUpdate;
  10. componentWillUnmount;
  11. обработчики кликов или событий, такие как onClickSubmit() или onChangeDescription();
  12. getter методы для render, такие как getSelectReason() или getFooterContent();
  13. произвольные render методы, такие как renderNavigation() или renderProfilePicture();
  14. render.

10.2 Как определять propTypes, defaultProps, contextTypes, и т.д.

import React from 'react';
import Proptypes from 'prop-types';

const propTypes = {
  id: PropTypes.number.isRequired,
  url: PropTypes.string.isRequired,
  text: PropTypes.string,
};

const defaultProps = {
  text: 'Hello World',
};

class Link extends React.Component {
  static methodsAreOk() {
    return true;
  }

  render() {
    return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a>;
  }
}

Link.propTypes = propTypes;
Link.defaultProps = defaultProps;

export default Link;

10.3 isMounted

Не используйте isMounted.

Почему? isMounted — это антипаттерн, который недоступен при использовании ES6 классов и который планируют официально признать устаревшим.