progway — программирование, IT
Попробуем устроить интерактив 👍 Предлагаю собрать ссылки на ваши пет-проекты. Я посмотрю их, а самые частые и популярные ошибки среди всех проектов я разберу в формате постов в этом канале Для начала ограничимся следующим: — открытый репозиторий на площадке…
Было тяжело, но я справился…
Как и обещал пару постов выше, я посмотрел проекты, что вы прислали на ревью. Этим постом я закрываю сбор ссылок, их и так было не мало)
Я просмотрел абсолютно всё, что было прислано, каждый проект.
Что в итоге:
1. Допишу пост с общими замечаниями, которые слишком малы для отдельного поста, и опубликую его где-то через полчаса-час
2. Далее будет 9 отдельных постов с разными темами по ревью. Их буду публиковать по 3 в день, чтобы совсем не заспамить канал
3. Ну и вернёмся к тому контенту, что я публикую обычно
Приз зрительской симпатии от меня получает приложение для подготовки в ЕГЭ. Проект объективно простенький, но я в какой-то момент залип и сидел буковки тыкал. Успел накликать больше 100 слов, пока вспомнил, а зачем я там, собственно)
Что ещё важно
Я создал чат канала. Кто не знает, каналу уже сильно больше 3 лет и всё это время он существовал без публичной обратной связи — со мной можно было связаться только в личку. Сейчас же я решил создать чат, что для меня шаг достаточно важный:
1. Идея с ревью была прикольная, но я понимаю, что дать какую-то качественную обратную связь в формате постов очень тяжело. Поэтому, я надеюсь, чатик станет адекватным местом для дискуссий
2. Под постами появятся комментарии и у вас появится великолепная возможность закидать меня помидорами 💔
Ссылка на чат
Спасибо за участие, это важно для меня
@prog_way_blog — #blog #review
Как и обещал пару постов выше, я посмотрел проекты, что вы прислали на ревью. Этим постом я закрываю сбор ссылок, их и так было не мало)
Я просмотрел абсолютно всё, что было прислано, каждый проект.
Что в итоге:
1. Допишу пост с общими замечаниями, которые слишком малы для отдельного поста, и опубликую его где-то через полчаса-час
2. Далее будет 9 отдельных постов с разными темами по ревью. Их буду публиковать по 3 в день, чтобы совсем не заспамить канал
3. Ну и вернёмся к тому контенту, что я публикую обычно
Приз зрительской симпатии от меня получает приложение для подготовки в ЕГЭ. Проект объективно простенький, но я в какой-то момент залип и сидел буковки тыкал. Успел накликать больше 100 слов, пока вспомнил, а зачем я там, собственно)
Что ещё важно
Я создал чат канала. Кто не знает, каналу уже сильно больше 3 лет и всё это время он существовал без публичной обратной связи — со мной можно было связаться только в личку. Сейчас же я решил создать чат, что для меня шаг достаточно важный:
1. Идея с ревью была прикольная, но я понимаю, что дать какую-то качественную обратную связь в формате постов очень тяжело. Поэтому, я надеюсь, чатик станет адекватным местом для дискуссий
2. Под постами появятся комментарии и у вас появится великолепная возможность закидать меня помидорами 💔
Ссылка на чат
Спасибо за участие, это важно для меня
@prog_way_blog — #blog #review
❤16🔥4🐳4👍1🍌1
Общие комментарии
1. Используйте TypeScript, на современном рынке даже джуну уже не достаточно примитивных знаний TS — большинство компаний требуют хороший опыт работы с типами, понимание дженериков и прочих не самых примитивных тем
2. Выносите хотя бы ёмкие константы куда-то из файла компонента, чтобы до самого компонента не приходилось листать 100+ строк при открытии файла
3. Выносите из компонента все независимые от его состояния сущности — в константы, в утилсы и в любое другое подходящее место. Это упростит чтение кода и зафиксирует ссылки
4. Не стесняйтесь создавать свои хуки, это ок. Есть примеры, где вызов
5. Очень много непонятных закомментированных частей кода в некоторых проектах. Комментируете = не надо = удаляете, восстановить всегда можно через гит
6. Используйте
7. Аккуратнее с инлайн стилями. Их можно использовать, но очень аккуратно и в крайних случаях. ИМХО лучше
8. Не используйте классовые компоненты, если в этом нет явной необходимости. Мир функциональных компонентов уже непобедим
9. Не храните ключи и прочие переменные в коде, используйте переменные окружения. Из кода можно легко компрометировать все ваши ключи, тем более проекты лежат в открытом доступе
10. Не нужно оборачивать в
11. Можно смириться с одним тернарным оператором в вёрстке, но когда их в одной конструкции сразу два… три… такое мы рефакторим обычными if-ами)
Отдельные посты по этому ревью будут выходить с завтрашнего дня
@prog_way_blog — чат — #review
1. Используйте TypeScript, на современном рынке даже джуну уже не достаточно примитивных знаний TS — большинство компаний требуют хороший опыт работы с типами, понимание дженериков и прочих не самых примитивных тем
2. Выносите хотя бы ёмкие константы куда-то из файла компонента, чтобы до самого компонента не приходилось листать 100+ строк при открытии файла
3. Выносите из компонента все независимые от его состояния сущности — в константы, в утилсы и в любое другое подходящее место. Это упростит чтение кода и зафиксирует ссылки
4. Не стесняйтесь создавать свои хуки, это ок. Есть примеры, где вызов
useEffect
достигает 50+ строк. Вынесите/разбейте, ничего страшного в этом нет5. Очень много непонятных закомментированных частей кода в некоторых проектах. Комментируете = не надо = удаляете, восстановить всегда можно через гит
6. Используйте
index
файлы для организации импортов, это делает импорты короче и читабельнее, а также позволяет проще управлять интерфейсом части кода. Используя index файл, вы явно определяете что можно импортировать, а что нельзя. Подробнее на доке7. Аккуратнее с инлайн стилями. Их можно использовать, но очень аккуратно и в крайних случаях. ИМХО лучше
!important
поставить, чем инлайнить. Ну а если используйте, то не пишите стили прямо в вёрстке. 99% случаев, которые я видел, не зависят от состояния компонента, так что можно легко создать константу вне компонента и зафиксировать ссылку на объект, что может быть очень полезно и в целом разгрузит вёрстку8. Не используйте классовые компоненты, если в этом нет явной необходимости. Мир функциональных компонентов уже непобедим
9. Не храните ключи и прочие переменные в коде, используйте переменные окружения. Из кода можно легко компрометировать все ваши ключи, тем более проекты лежат в открытом доступе
10. Не нужно оборачивать в
memo
, useMemo
, useCallback
абсолютно всё. В ревью видел много мест, где memo
используется там, где компонент имеет 1 рендер за весь жизненный цикл и без него, а useCallback
скорее замедляет приложением, чем оптимизирует 11. Можно смириться с одним тернарным оператором в вёрстке, но когда их в одной конструкции сразу два… три… такое мы рефакторим обычными if-ами)
Отдельные посты по этому ревью будут выходить с завтрашнего дня
@prog_way_blog — чат — #review
🔥37👍10❤4🐳4🍌1🫡1
Использование gap вместо margin
Начнем комментарии по проектам с популярной ошибки — использование
Почему использовать
1. Легче изменять код — чаще всего отступы везде одинаковые в таких списках. При изменении отступов, проще изменить его в одном месте, чем для каждого компонента вёрстки
2. Более чистый код, отсутствие дублирования стилей
3. Лучше производительность — браузеру куда проще обработать
Что такое свойство gap
Что такое row-gap, column-gap
@prog_way_blog — #web #review
Начнем комментарии по проектам с популярной ошибки — использование
margin
вместо gap
. Посты постараюсь делать покороче, не хочу развозить на это всю ленту.Почему использовать
gap
лучше margin
:1. Легче изменять код — чаще всего отступы везде одинаковые в таких списках. При изменении отступов, проще изменить его в одном месте, чем для каждого компонента вёрстки
2. Более чистый код, отсутствие дублирования стилей
3. Лучше производительность — браузеру куда проще обработать
gap
в структурированной сетке, чем нарисовать для каждого отдельного элемента собственный отступЧто такое свойство gap
Что такое row-gap, column-gap
@prog_way_blog — #web #review
👍26🔥5🐳4❤2🍌1👀1
Файловая структура проекта
Очень важно понимать, что файловая структура — это самый верный помощник разработчика в навигации по проекту.
В некоторых проектах, что прислали на ревью, в файловой структуре бывало достаточно тяжело разобраться. Тут и
Чтобы путаницы не возникало при переходе от проекта к проекту, стоит использовать общепринятые нормы оформления проектов, которые под собой подразумевают в том числе организованную файловую структуру. Для примера, это может быть FSD, который сейчас на пике популярности.
Также стоит руководствоваться просто логикой. Лично для меня не до конца понятно, когда в папку
Компоненты я бы сложил к компонентам, даже если они утилитарные (пример на фото), а валидаторы в сервисы, хотя момент всё таки спорный. Лично я бы сделал что-то типа
Тут
Вызов самого валидатора был бы следующий:
Я люблю такие оргструктуры, это мой код стайл. Кому-то он покажется странным, но его плюсы очевидны:
1. Строгая иерархичность и однозначность расположения валидаторов
2. Простой поиск того, что тебе нужно
3. Красивые импорты
4. Простое управление публичным интерфейсом сущности
Архитектурная методология Feature Slices Design
@prog_way_blog — #review
Очень важно понимать, что файловая структура — это самый верный помощник разработчика в навигации по проекту.
В некоторых проектах, что прислали на ревью, в файловой структуре бывало достаточно тяжело разобраться. Тут и
pages
внутри components
, и другие чудеса. Чтобы путаницы не возникало при переходе от проекта к проекту, стоит использовать общепринятые нормы оформления проектов, которые под собой подразумевают в том числе организованную файловую структуру. Для примера, это может быть FSD, который сейчас на пике популярности.
Также стоит руководствоваться просто логикой. Лично для меня не до конца понятно, когда в папку
utils
складывают компоненты и валидаторы, а константы в папку services
Компоненты я бы сложил к компонентам, даже если они утилитарные (пример на фото), а валидаторы в сервисы, хотя момент всё таки спорный. Лично я бы сделал что-то типа
ValidatorService
и разделил бы его на два дочерних сервиса: InputValidator
и ModelValidator
Тут
InputValidator
отвечал бы, очевидно, за ввод, а ModelValidator
для валидации моделей, например, валидации payload’a из ответа апишки.Вызов самого валидатора был бы следующий:
ValidatorService.InputValidator.email(email)
Я люблю такие оргструктуры, это мой код стайл. Кому-то он покажется странным, но его плюсы очевидны:
1. Строгая иерархичность и однозначность расположения валидаторов
2. Простой поиск того, что тебе нужно
3. Красивые импорты
4. Простое управление публичным интерфейсом сущности
Архитектурная методология Feature Slices Design
@prog_way_blog — #review
👍22🐳6❤2🔥2🍌1
Нейминг файлов
1. Определитесь в каком стиле именуете файлы. В одном проекте не должно существовать файлов
2. Я советовал бы переименовать
3. В названии файлов стоит избегать аббревиатур и сокращений, всегда удивляла мания экономить буквы у разработчиков. Лучше использовать только общепринятые сокращения, например,
@prog_way_blog — #review
1. Определитесь в каком стиле именуете файлы. В одном проекте не должно существовать файлов
MarktetTrends.jsx
, filterSlice.js
, table.hook.jsx
. Если делаем групповой суффикс к файлу, типа *.component.jsx
, то делаем везде. Если используем camelCase
, то везде. Выглядит симпатичнее, искать проще, нет визуальной каши.2. Я советовал бы переименовать
table.hook.jsx
в use-table.hool.jsx
или use-table.jsx
. Вы же знаете, что с use начинаются хуки. В поиске инстинктивно напишете use table
и файл table.hook.jsx
просто не найдёте. Неймингом можно спасти не одну нервную клетку, так же как и убить.3. В названии файлов стоит избегать аббревиатур и сокращений, всегда удивляла мания экономить буквы у разработчиков. Лучше использовать только общепринятые сокращения, например,
http
, чтобы избежать недопониманий@prog_way_blog — #review
👍17🔥4🐳4🍌1
Линтеры
Я мог бы кучу моментов подметить на тему того, что “тут кавычки не те”, а “тут отступы кривые”. Настройте линтер. На подобные комменты в процессе ревью вообще отвлекаться — антипаттерн. Если ревью состоит из того, что вам указывают где какую кавычку лучше поставить, то это бред, а не ревью. Подобные вопросы должны решаться автоматизировано.
Другая проблема — в некоторых проектах есть eslint/prettier, супер, круто, но видно же, что код отформатирован не по ним, а в некоторых местах вообще стоят
@prog_way_blog — #review
Я мог бы кучу моментов подметить на тему того, что “тут кавычки не те”, а “тут отступы кривые”. Настройте линтер. На подобные комменты в процессе ревью вообще отвлекаться — антипаттерн. Если ревью состоит из того, что вам указывают где какую кавычку лучше поставить, то это бред, а не ревью. Подобные вопросы должны решаться автоматизировано.
Другая проблема — в некоторых проектах есть eslint/prettier, супер, круто, но видно же, что код отформатирован не по ним, а в некоторых местах вообще стоят
eslint-disable
комменты. Пожалуйста, помимо закидывания конфиги в проект, убедитесь, что линтер реально работает и форматирует всё так, как ожидается. Ну и eslint-disable
использовать тоже очевидно не нужно) @prog_way_blog — #review
👍16🐳9🔥2🤯2🍌1
Комплексные состояния
Есть такой код:
Как его можно исправить:
Почему я считаю что так лучше:
1. Проще следить за иммутабельностью состояния, так как не нужно постоянно разворачивать
2. Легче контролировать зависимости и сайд эффекты, если на состояние завязывается, например,
3. Визуально в использовании считается легче
5. Нет необходимости создавать ещё какой-то тип
В целом, можно и так оставить то. Работать будет, и даже уже сейчас работает. Но лично мне такое бьет по глазам.
@prog_way_blog —#typescript #web #review
Есть такой код:
const [userData, setUserData] = React.useState<IData>({
identifier: "",
password: "",
});
Как его можно исправить:
const [identifier, setIdentifier] = useState<string>("");
const [password, setPassword] = useState<string>("");
Почему я считаю что так лучше:
1. Проще следить за иммутабельностью состояния, так как не нужно постоянно разворачивать
prev
объект2. Легче контролировать зависимости и сайд эффекты, если на состояние завязывается, например,
useEffect
3. Визуально в использовании считается легче
4. useState
вместо React.useState
, ИМХО приятнее5. Нет необходимости создавать ещё какой-то тип
В целом, можно и так оставить то. Работать будет, и даже уже сейчас работает. Но лично мне такое бьет по глазам.
@prog_way_blog —#typescript #web #review
🔥14🐳6👍2🍌1
Магические числа
Немного магии — не всегда приятно. Есть код:
Как можно сделать:
Как на самом деле нужно сделать:
Так нужно сделать, чтобы не завязываться на число
@prog_way_blog — #review
Немного магии — не всегда приятно. Есть код:
date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000));
Как можно сделать:
const MILLISECONDS_PER_YEAR = 365 * 24 * 60 * 60 * 1000;
date.setTime(date.getTime() + MILLISECONDS_PER_YEAR);
Как на самом деле нужно сделать:
const date = new Date();
date.setFullYear(date.getFullYear() + 1);
Так нужно сделать, чтобы не завязываться на число
365
, так как год бывает високосным.@prog_way_blog — #review
👍28🐳3❤2🔥2🍌2🗿2
Ответственность состояния
Есть код:
Как можно было бы сделать:
Ну и в зависимости от
@prog_way_blog — #review
Есть код:
const [isFormSubmited, setFormSubmited] = React.useState({
submited: false,
submitedText: "",
submitedError: "",
submitedColor: "",
});
setFormSubmited({
submited: true,
submitedText: "Вы успешно зарегистрировались!",
submitedError: "",
submitedColor: "#238C47",
});
Как можно было бы сделать:
enum FormState {
Success,
Error,
WaitingForAction
}
const [formState, setFormState] = useState<FormState>(FormState.WaitingForAction);
Ну и в зависимости от
formState
рисовать любую фразу любого цвета, которого хочется. В этом случае вообще не понятно почему цвет текста и текст сообщения были вынесены в состояние. Оставьте это в вёрстке, зачем в состояние то.@prog_way_blog — #review
👍19🔥4🐳3🤔1
Страшные рефы
Есть код:
Как сделал бы я:
Цитата из доки реакта: “Не вызывайте хуки внутри циклов, условных операторов или вложенных функций. Вместо этого всегда используйте хуки только внутри React-функций, до возврата какого-либо значения из них.”. Если это правило не соблюдать, то можно самых странных ошибок огрести.
Подробнее в официальном руководстве
@prog_way_blog — #react #review
Есть код:
const items = [1, 2, 3, 4];
const itemRefs: React.RefObject<HTMLDivElement>[] = items.map(() =>
useRef(null),
);
// и далее в вёрстке
ref={itemRefs[index]}
Как сделал бы я:
// вынести из компонента
const items = [1, 2, 3, 4];
// внутри компонента
const itemRefs = useRef([])
// и внутри вёрстки
// index берется из .map, так как элементы на
// страницу вставляются из списка
ref={element = inputRef.current[index] = element}
Цитата из доки реакта: “Не вызывайте хуки внутри циклов, условных операторов или вложенных функций. Вместо этого всегда используйте хуки только внутри React-функций, до возврата какого-либо значения из них.”. Если это правило не соблюдать, то можно самых странных ошибок огрести.
Подробнее в официальном руководстве
@prog_way_blog — #react #review
🔥11🐳9❤2🤔1
Зачем нужен useCallback
Очень распространенная ошибка, которая говорит о том, что мало кто понимает что такое
Важный вопрос, будет ли ререндерится
И ответ тут очевиден —конечно же да! Не смотря на то, что функцию мы мемоизировали и ссылка на саму функцию у нас не изменилась благодаря
Чтобы получить ожидаемое поведение, необходимо сделать очень важную вещь, а именно — мемоизировать и сам дочерний компонент:
Вот только так и только тогда мы перестанем ререндерить дочерние компоненты, так как пропсы не изменились. При ревью я заметил много случаев, когда useCallback использовать просто не нужно было, но он был.
А ещё много таких было кейсов:
Тут смысл
Пример из доки реакта
@prog_way_blog — #react #review
Очень распространенная ошибка, которая говорит о том, что мало кто понимает что такое
useCallback
и зачем он нужен.Важный вопрос, будет ли ререндерится
Component
при ререндере родителя?const Parent = () => {
const foo = useCallback(() => {
}, [])
return <Component foo={foo} />
}
const Component = (props) => { ... }
И ответ тут очевиден —
useCallback
, мы всё равно перерендерим Component
, поскольку рендерится родитель. Чтобы получить ожидаемое поведение, необходимо сделать очень важную вещь, а именно — мемоизировать и сам дочерний компонент:
const Component = memo((props) => { ... })
Вот только так и только тогда мы перестанем ререндерить дочерние компоненты, так как пропсы не изменились. При ревью я заметил много случаев, когда useCallback использовать просто не нужно было, но он был.
А ещё много таких было кейсов:
const Component = () => {
const foo = useCallback(() => {
}, [])
return <button onClick={() => foo()} />
}
Тут смысл
useCallback
теряется вдвойне, так как в пропсах мы всё равно пересоздаём функцию на каждый рендер вот тут: onClick={() => foo()}
Пример из доки реакта
@prog_way_blog — #react #review
👍20🐳4🔥3🤔1