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

Facebook
Twitter
Vkontakte
Telegram

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

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, и т.д.

Как определять 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.4 isMounted

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

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