Style Guide для разработки компонентов на React

Style Guide для разработки компонентов на React


05.03.2019
/
oberset

Базовые правила

1) Определяйте один React компонент в одном файле.

2) Всегда используйте JSX синтаксис.

3) Разбивайте компоненты на Presentional и Container компоненты.

4) Не используйте React.createElement, если только вы не инициализируете приложение из не-JSX файла.

Название переменных и методов.
<ListItem
//Все сигналы доступны через onEvent
onSelect={()=>{}} (не selectFunc, select, handleSelect)
onDrop={()=>{}}
// Не используются сокращения
value={1} (не val)
item={1} (не itm)
/>

class Select {
// обработчики событий именуются по правилу handleEvent
handleSelect(){ // а не onSelect, listenSelect
}
handleClick(){
}

// все методы должны быть действиями(глаголами) Verb
requestFile = () => {} а не fileRequest, fileFromBackend
refreshIcon = () => {} а не iconRefresher

closeMenu = () => {
// переменные boolean без is/has (в редких случаях допустимо)
const done = items.length === 0; (не hasDone)
const selected = items[1] === true (не isSelected)
}
}

Не используйте React.createClass.
// bad
const Listing = React.createClass({
...
render() { return <div>{this.state.hello}</div>; }
});

// good
class Listing extends React.Component<ListingProps, ListingState> {
...
render() { return <div>{this.state.hello}</div>; }
}

Компоненты стоит создавать через класс React.Component или React.PureComponent только если у них есть внутреннее состояние (state), ссылки (refs) или требуется использование жизненного цикла (lifecycle).

Установка состояния компонента

Первоначальное состояние компонента устанавливаем в конструкторе.
// bad
class Example extends React.Component<ExampleProps, ExampleState> {
state = {
value: this.props.value
}
}

// good
class Example extends React.Component<ExampleProps, ExampleState> {
constructor(props) {
super(props);
this.state = {
value: props.value
}
}
}

Вообще лучше избегать стейта компонента. Если вам требуется пересчитывать стейт при изменении props, то воспользуйтесь методом getDerivedStateFromProps. Если state всегда вычисляется как функция от props, то лучше вместо него воспользоваться мемоизацией.

Обновление состояния компонента

Смена состояния компонента происходит путем передачи в setState объекта, в случае если новый state опирается на текущий state, то используем функциональный setState.
// bad
class Example extends React.Component {
handleChange = (event) => {
const {target} = event;
// useless use of functional setState
this.setState(() => ({value: target.value}))
}
}

// good
class Example extends React.Component {
handleChange = (event) => {
const {target} = event;
this.setState({value: target.value})
}
}

// bad
class Example extends React.Component<ExampleProps, ExampleState> {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}

handleClick = () => {
// multiple calls during the same cycle may be batched together
this.setState({counter: this.state.counter + 1})
}
}

// good
class Example extends React.Component<ExampleProps, ExampleState> {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}

handleClick = () => {
this.setState((state) => ({counter: state.counter + 1}))
}
}

Именование

Используйте всегда файлы с расширением .jsx для React компонентов. Используйте hyphen-style для названия файла. Как правило, файлы содержат одну сущность. В таких случаях название файла должно соответствовать названию сущности.
import * as React from 'react';
...
export class OverlayLayout extends React.Component<OverlayLayoutProps> {
...
render() {
const {children, overlayVisibility, position, pageisForceReloaded} = this.props;
...
}
}

Используйте Индексные файлы (index.js) для экспорта открытых частей модуля. Называйте файлы исходя из сути содержимого, например:
header.jsx, siderbar.sass, primary-button.jsx, overlay-layout.jsx. Общие названия допустимы на уровне абстрактных модулей/компонентов.

Не используйте сокращения в названиях функций.
// bad
function q() {
// ...stuff...
}

// good
function query() {
// ..stuff..
}

Используйте camelCase для объектов и функций.
// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}

// good
const thisIsMyObject = {};
function thisIsMyFunction() {}

Используйте PascalCase для конструкторов и классов.
// bad
function user(options) {
this.name = options.name;
}

const bad = new user({
name: 'nope',
});

// good
class User {
constructor(options) {
this.name = options.name;
}
}
const good = new User({
name: 'yup',
});

Распространенные, устоявшиеся сокращения в именах должны быть в одном регистре.
// bad
import {SmsContainer} from './containers/SmsContainer';

// bad
const HttpRequests = [
// ...
];

// good
import {SMSContainer} from './containers/sms-container';

// good
const HTTPRequests = [
// ...
];

Кавычки

Всегда используйте двойные кавычки («) для JSX аттрибутов, а одинарные (‘) для всего остального кода на Javascript. Обычные HTML атрибуты также как правило используют двойные кавычки вместо одинарных. Таким образом, JSX атрибуты следуют этой конвенции.
// bad
<Foo bar='bar' />

// good
<Foo bar="bar" />

// bad
<Foo style={{left: "20px"}} />

// good
<Foo style={{left: '20px'}} />

Пробелы

Всегда добавляйте один пробел в самозакрывающийся тэг.
// bad
<Foo/>

// very bad
<Foo />

// bad
<Foo
/>

// good
<Foo />

Не отделяйте фигурные скобки от их содержимого пробелами.
// bad
<Foo bar={ baz } />

// good
<Foo bar={baz} />

Свойства компонентов

Не используйте стандартные названия DOM-свойств для других целей. Ожидается, что свойства style и className используются только для одной цели. Если не следовать этому правилу в приложении, то его код становится менее читаемым и поддерживаемым, и может являться причиной дефектов.
// bad
<MyComponent />

// good
<MyComponent variant="fancy" />

Используйте camelCase для именования свойств компонента.
// bad
<Foo
UserName="hello"
phone_number={12345678}
/>

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

Используйте сокращенную запись для булевых свойств.
// bad
<Foo
hidden={true}
/>

// good
<Foo
hidden
/>

Избегайте дублирование названий свойств и названия компонента. Например, для компонента ImagesList лучше использовать items, а не images.

Избегайте использования индексов массива как значение свойства key. Предпочтительнее будет уникальный идентификатор.
// bad
{todos.map((todo, index) =>
<Todo
{...todo}
key={index}
/>
)}

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

Всегда определяйте defaultProps для всех не обязательных свойств.

Ссылки (refs)

Всегда используйте в качестве значения ref поле, созданное с помощью React.createRef().
// bad
<Foo
ref="myRef"
/>

// bad
<Foo
ref={(ref) => { this.myRef = ref; }}
/>

// good
class MyComponent extends React.Component {
myRef = React.createRef();
render() {
return <div ref={this.myRef} />;
}
}

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

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

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

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

// good, when single line
render() {
const body = <div>hello</div>;
return <MyComponent>{body}</MyComponent>;
}

Тэги

Всегда используйте самозакрывающиеся тэги, если они не имеют потомков.
// bad
<Foo className="stuff"></Foo>

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

Если у компонента свойства расположены на нескольких строках, закрывайте тэг на новой строке.
// bad
<Foo
bar="bar"
baz="baz" />

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

Методы

Используйте стрелочные функции (arrow functions) для замыкания локальных переменных.
function ItemList(props) {
return (
<ul>
{props.items.map((item, index) => (
<Item
key={item.key}
onClick={() => doSomethingWith(item.name, index)}
/>
))}
</ul>
);
}

Чтобы обойтись без привязки this к обработчикам событий, определяйте их как свойства класса, где значением будет стрелочная (arrow) функция.
// bad
class extends React.Component<...> {
onClickDiv() {
// do stuff
}

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

// good
class extends React.Component<...> {
onClickDiv = () => {
// do stuff
}

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

Не используйте символ подчеркивания для частных (private) методов React компонента.
// bad
React.createClass({
_onClickSubmit() {
// do stuff
},

// other stuff
});

// good
class extends React.Component<...> {
onClickSubmit() {
// do stuff
}

// other stuff
}

Подобный знак нижнего подчеркивания (_) используется в некоторых языках для указания метода, как частного (private). Но, в отличие от других языков программирования, у JavaScript не реализована подобная функциональность, все методы — public. И не смотря на использования префикса _, он не делает методы по-настоящему частными. Для более глубокого изучения данного вопроса изучите обсуждения #1024 и #490.

Использование Хуков в React

Хуки в React – это новая возможность, которая появилась в версии 16.8. Они позволяют использовать состояние и другие возможности компонентов React в рамках функционального программирования.

Поиск и проверка значений в массиве на Javascript

Примеры поиска значений в массиве с помощью методов find, findIndex, includes, every и других.

Зачем нужен реверс-инжиниринг?

Реверс-инжиниринг или обратная разработка – это процесс преобразования готовой откомпилированной программы в первозданное состояние, то есть в исходный код.