Общие правила определены в eslint
, могут меняться по согласованию участников проекта.
Для авто форматирования кода используется prettier
.
Отступы в коде — 2 пробела.
Названия файлов и директорий в нижнем регистре через дефис. kebab стиль. /some-name/index.js
.
Файлы компонент, модулей и потенциально расширяемых на несколько файлов частей кода, группируются в директории.
index.js
, actions.js
, style.less
, favicon.png
articles
├──state.js
├──actions.js
└──reducer.js
...
button
├──index.js
├──style.less
└──checked.svg
В одном файле кода содержится логика с однозначным назначением, не должно быть кучи всего в одном месте.
Упорядочивать функции в классе (объекте) по приоритету или последовательности исполнения — чтобы был хоть какой-то порядок для быстрой ориентации по коду.
Не развертывать свойства объекта в переменные без весомой на это причины, так как ниже по коду сложнее сориентироваться, от куда переменная.
Лучше написать props.value
чем value
. Лучше, завертывать в объекты переменные по общим признаам,
например callbacks.onClick
- будет ясно где объявлена. Это как с группировкой файлов в поддиректории, чтобы
легче ориентироваться в них.
Логика должна быть четко сгруппирована на логические блоки. Ни в коем случаи не писать где попало новый хук, объявлять переменную или выполнять импорт. Разработчик должен интуитивно знать, где искать определение функции или переменной
useInit()
.select = useSelectMap()
,[stateActive, setStateActive] = useState()
callbacks = {}
.options = {}
.renders = {}
.Импорт файлов приложения через алиас "@src/"
вместо относительных путей.
Комментировать строки кода, если логика неочевидная, не типовая, сложная.
Комментировать назначение функций в jsDoc формате: краткое описание, параметры @param
, возвращаемое значение @return
и другие опционально.
Пример кода с логическими блоками
import CustomOption from '@src/components/elements/custom-option';
/**
* Пример компонента с логическими блоками
* @param props {Object} Свойства компонента
* @return {Object}
*/
function SomeCompoennt(props){
// Состояние из redux
const select = useSelectorMap(state => ({
active: state.categories.active,
items: state.categories.items
}));
// Функции обратного вызова
const callbacks = {
onClick: useCallback(()=>{...}, []),
onSubmit: useCallback(()=>{...}, []),
}
// Замороженные опции
const options = {
items: useMemo(()=>{...}, [])
}
// Отдельные функции рендера
const renders = {
item: useCallback((itemProps)=>(<CustomOption {...itemProps}/>), []),
}
return (
<select onClick={callbacks.onClick} className={themes('Select', {'disabled': props.disabled})}>
{options.items.map(item => (renders.item(item)))}
</div>
)
}