React является JavaScript-библиотекой, поэтому помимо нижеизложенных, следует также придерживаться правил оформления JavaScript кода.
- Создание компонента без внутреннего состояния и ссылок
- Именование
2.1. Расширения
2.2. Имя файла
2.3. Именование переменной
2.4. Именование компонента
2.5. Именование компонента высшего порядка
2.6. Названия свойств - Выравнивание
- Кавычки
- Пробелы
- Свойства (
Props
)
6.1. Названия свойств
6.2. Значения свойств
6.3. Свойствоkey
6.4.defaultProps
- Круглые скобки
- Теги
- Методы
9.1. Замыкание локальных переменных
9.2. Привязка обработчиков событий
9.3. Возврат значений вrender
- Последовательность
10.1. Последовательность вызова методов внутри компонента
10.2. Как определятьpropTypes
,defaultProps
,contextTypes
, и т.д.
10.3.isMounted
Если у компонента нет состояния (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>;
}
}
Используйте расширение .js для компонентов React.
Используйте PascalCase для названий файлов, например, ReservationCard.js.
Используйте PascalCase для компонентов React.
Хорошо
import ReservationCard from './ReservationCard';
Плохо
import reservationCard from './ReservationCard';
Используйте camelCase для экземпляров компонентов React.
Хорошо
const reservationItem = <ReservationCard />;
Плохо
const ReservationItem = <ReservationCard />;
Называйте файлы так же как и компоненты. Например, ReservationCard.js должен содержать внутри компонент ReservationCard. Однако корневые компоненты в директории должны лежать в файле index.js, и в этом случае название папки должно быть таким же, как название компонента.
Хорошо
import Footer from './Footer';
Плохо
import Footer from './Footer/Footer';
Плохо
import Footer from './Footer/index';
Используйте сочетание имени компонента высшего порядка и имени переданного в него компонента как свойство 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 />;
}
}
Избегайте использования названий свойств DOM-компонента для других целей.
Почему? Люди ожидают, что такие свойства как style
и className
имеют одно определенное значение. Изменение этого API в вашем приложении ухудшает читабельность и поддержку кода, что может приводить к ошибкам.
Хорошо
<MyComponent variant="fancy" />
Плохо
<MyComponent style="fancy" />
Следуйте приведенным ниже стилям для JSX-синтаксиса.
Хорошо
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
/>
Плохо
<Foo superLongParam="bar"
anotherSuperLongParam="baz" />
Если свойства помещаются на одну строку, оставляйте их на одной строке.
<Foo bar="bar" />
Отступ у дочерних элементов задается как обычно.
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
>
<Quux />
</Foo>
Всегда используйте двойные кавычки: ("
) для JSX-атрибутов.
Хорошо
<Foo bar="bar" userName="hello" />
Плохо
<Foo bar='bar' userName='hello' />
Плохо
<Foo bar='bar' userName="hello" />
Не отделяйте фигурные скобки пробелами в JSX.
Хорошо
<Foo bar={baz} />
Плохо
<Foo bar={ baz } />
Всегда используйте camelCase для названий свойств.
Хорошо
<Foo
userName="hello"
phoneNumber={12345678}
/>
Плохо
<Foo
UserName="hello"
phone_number={12345678}
/>
Не указывайте значение свойства, когда оно явно true
.
Хорошо
<Foo
hidden
/>
Плохо
<Foo
hidden={true}
/>
Не используйте индексы элементов массива в качестве свойства key
. Отдавайте предпочтение уникальному ID
.
Хорошо
{todos.map(todo => (
<Todo
{...todo}
key={todo.id}
/>
))}
Плохо
{todos.map((todo, index) =>
<Todo
{...todo}
key={index}
/>
)}
Всегда указывайте явные 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,
};
Оборачивайте в скобки 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>;
}
Всегда используйте самозакрывающиеся теги, если у элемента нет дочерних элементов.
Хорошо
<Foo className="stuff" />
Плохо
<Foo className="stuff"></Foo>
Если ваш компонент имеет множество свойств, которые располагаются на нескольких строчках, то закрывайте тег на новой строке.
Хорошо
<Foo
bar="bar"
baz="baz"
/>
Плохо
<Foo
bar="bar"
baz="baz" />
Используйте стрелочные функции для замыкания локальных переменных.
Хорошо
function ItemList(props) {
return (
<ul>
{props.items.map((item, index) => (
<Item
key={item.key}
onClick={() => doSomethingWith(item.name, index)}
/>
))}
</ul>
);
}
Привязывайте обработчики событий для метода 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)} />;
}
}
Всегда возвращайте значение в методах render
.
Хорошо
render() {
return (<div />);
}
Плохо
render() {
(<div />);
}
Последовательность для class extends React.Component
:
- произвольные
static
методы; constructor
;getChildContext
;componentWillMount
;componentDidMount
;componentWillReceiveProps
;shouldComponentUpdate
;componentWillUpdate
;componentDidUpdate
;componentWillUnmount
;- обработчики кликов или событий, такие как
onClickSubmit()
илиonChangeDescription()
; getter
методы дляrender
, такие какgetSelectReason()
илиgetFooterContent()
;- произвольные
render
методы, такие какrenderNavigation()
илиrenderProfilePicture()
; render
.
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;
Не используйте isMounted
.
Почему? isMounted
— это антипаттерн, который недоступен при использовании ES6 классов и который планируют официально признать устаревшим.