Telegram Web
Метод массива toSorted

Относительно новые фишки языка уже просачиваются на собеседования, поэтому ближайшие посты будут посвящены разбору нововведений спецификации ECMAScript 2023. В этой спецификации было представлено много новых методов, которые позволяют упростить работу с массивами.

toSorted — это метод массива, который работает аналогично уже давно существующему методу sort, а именно, как и ожидается, сортирует массив.

Проблема обычного метода sort заключается в том что его вызов мутирует исходный массив. Это может вызвать неудобства и проблемы в тех местах, где нам запрещено менять исходные данные, например при обработке экшенов в redux.

const nums = [1, 4, 3, 2]
nums.sort()
console.log(nums) // [1, 2, 3, 4]


В этом примере в консоли мы увидим уже отсортированный массив, несмотря на то, что, казалось бы, никак не обрабатывали результат вызова метода. На самом деле, метод sort напрямую изменяет массив, для которого был вызван. Для решения такой проблемы часто можно видеть следующий хак:

const nums = [1, 4, 3, 2]
const newNums = [...nums].sort()

console.log(nums) // [1, 4, 3, 2]
console.log(newNums) // [1, 2, 3, 4]


И как раз для упрощения этой операции в спецификации и появился новый метод — toSorted. Его работу в чём то можно сравнить с методами map и filter, а именно в том, что все эти метода совершают какие-то действия только над копией массива не затрагивая изначальный, при это возвращая полностью новый массив.

На примере это будет выглядеть следующим образом:

const nums = [1, 4, 3, 2]
const newNums = nums.toSorted()

console.log(nums) // [1, 4, 3, 2]
console.log(newNums) // [1, 2, 3, 4]


Не сказал бы, что что-то невероятно сильно изменилось, но такая запись точно безопаснее, проще и визуально выглядит гораздо легче.

Аналогичные замены появились и для методов reverse и splice. Для них еще один небольшой пример:

const nums = [1, 2, 3, 4];
const reversed = nums.toReversed();
console.log(nums) // [1, 2, 3, 4]
console.log(reversed) // [4, 3, 2, 1]

const nums = [1, 2, 3, 4];
const spliced = nums.toSpliced(0, 1);
console.log(nums) // [1, 2, 3, 4]
console.log(spiced) // [2, 3, 4]


Это не все нововведения ECMAScript 2023, но это их весомая часть. Разбор остальных нововведений будет в скором времени.

Спасибо за прочтение, это важно для меня ❤️

#javascript #theory #web #data
50👍11🔥8🐳6
Event: особенности target и currentTarget

Напоминаю, что при обработке события, функция-обработчик получает первым аргументом объект события Event, который содержит различные поля, это самое событие идентифицирующие. Одними из таких полей являются свойства target и currentTarget, рассмотрим их поближе:

event.target — это тот элемент вёрстки, который вызвал событие.
event.currentTarget — это тот элемент вёрстки, к которому прикреплен обработчик события.

Скорее всего, из сухих определений мало что можно понять, поэтому рассмотрим пример:

<button id="outer">
Outer Button

// всегда будем кликать именно на
// внутреннюю кнопку
<button id="inner">Inner Button</button>
</button>


const outerButton = document.getElementById('outer');
const innerButton = document.getElementById('inner');

outerButton.addEventListener('click', function(event) {
// выведет 'inner', потому что этот элемент вызвал событие
console.log('event.target:', event.target.id);'
// выведет 'outer', так как обработчик принадлежит именно
// внешней кнопке
console.log('event.currentTarget:', event.currentTarget.id); // выведет 'outer'
});

innerButton.addEventListener('click', function(event) {
// ожидаемо увидим 'inner'
console.log('event.target:', event.target.id);
// также ожидаемо будет 'inner', так как этот обработчик
// принадлежит уже innerButton
console.log('event.currentTarget:', event.currentTarget.id);
});


Тут мы видим, что event.target всегда ссылается на кнопку inner, поскольку именно она и триггерит событие, когда пользователь на нее кликает. В свою очередь, event.currentTarget ссылается именно на тот элемент, чей обработчик сработал.

Эта тема крайне тесно связана с событийной моделью браузера, о которой можно прочитать в одном из моих прошлых постов.

Различие между event.target и event.currentTarget особенно полезно при работе с вложенными элементами, когда обработчики событий привязаны к родительским элементам, то есть при делегировании событий, о чём я также писал ранее. Ну и на собесе поможет, конечно же)

Спасибо за прочтение, это важно для меня ❤️

#theory #web #javascript
30👍16🔥2🐳2
Двухфакторная аутентификация и факторы аутентификации

Фактор аутентификации — это способ подтверждения личности пользователя.

Существует несколько факторов аутентификации:

— Фактор знания — это информация, которую может знать конкретный пользователь, например, пароль, PIN-код или ответ на секретный вопрос

— Фактор владения — это что-то, что пользователь имеет, например, мобильное устройство для получения одноразового кода аутентификации через SMS или приложение аутентификатор

— Фактор индивидуальности — это что-то, что является частью пользователя, например, биометрические данные, такие как скан отпечатка пальца, сетчатки или параметры распознавания лица

Когда пользователь вводит свой пароль, то есть подтверждает первый фактор, система запрашивает дополнительный фактор подтверждения, чтобы убедиться в его личности. Такой подход к аутентификации называется двухфакторным.

Двухфакторная аутентификация (2FA) — подход к выполнению аутентификации пользователя, когда для идентификации личности используется сразу два фактора.

В последнее время двухфакторная аутентификация стала стандартом, так как это значимо повышает безопасность приложений, аккаунтов пользователей, а значит и безопасность их данных.

Также важно знать, что среди факторов аутентификации присутствует некая иерархия, то есть, фактор индивидуальности является более надежным, чем фактор владения, а фактор владения — более надежным, чем фактор знания.

Комбинировать различные факторы аутентификации можно в любом виде, но самые распространенные из них:
— Номер телефона + SMS — вы не просто знаете номер телефона, но и владеете им
— Почта + пароль + код из сообщения на почту — вы не просто знаете учетные данные, но и имеете доступ к почте
— Face ID — вы обладаете индивидуальными чертами лица
— Отпечаток пальца

Возможно, есть ещё какие-то распространенные связки, но, кажется, что основные я вспомнил

Также даю ссылку на свой прошлый пост, где я объяснил разницу между авторизацией и аутентификацией. Это важно в контексте этого поста.

Спасибо за прочтение, это важно для меня ❤️

#theory #data
🔥31🐳7👍6
Измерение времени в JavaScript

JavaScript предлагает несколько способов для измерения времени выполнения кода, которые могут быть полезны при оптимизации и анализе производительности. Я думаю, что все мы знаем про глобальный объект Date, который позволяет работать нам с таймстемпами, но также есть ещё один менее известный способ — Perfomance API

Как атрибут глобального объекта window, performance предоставляет пользователям лишь набор методов. И эти методы позволяют работать с производительностью более точно. Например, метод performance.now() возвращает количество миллисекунд с высокой точностью, прошедших с начала исполнения текущей страницы.

const start = performance.now();

// Код, который нужно измерить

const end = performance.now();

console.log(`Время выполнения: ${end - start} миллисекунд`);


То же самое можно сделать с использованием Date, но почему это не лучший способ?
1. perfomance.now() более точен и возвращает время с точностью до тысячных долей миллисекунды (микросекунды). Это позволяет более точно рассчитывать время выполнения, особенно если речь идёт о коротких по времени операциях.
2. Меньше накладных расходов. Date — очень тяжелый конструктор, его вызов стоит дорого. В свою очередь, Perfomance API не только занимает меньше времени, но и исключает связанные с временем вызова погрешности из расчётов. Особенно может быть полезно, если необходимо измерять время каждой итерации одного цикла, например.

Если подводить итог, то я просто за то, чтобы использовать инструменты по назначению. Perfomance API решает крайне важную и популярную задачу, это самый точный и универсальный инструмент для выполнения замеров времени. Мы всё ещё можем использовать Date для этих задач, но зачем? Это как console.log’ами дебажить. Ой.. Я ведь не один так делаю, да?)

#web #theory #data #javascript
👍23🐳151
This media is not supported in your browser
VIEW IN TELEGRAM
Что такое псевдоэлементы

Псевдоэлементы — это специальные ключевые слова, которые используются для дополнительной стилизации страницы без изменения HTML.

Одними из наиболее распространенных псевдоэлементов являются ::before и ::after. Они позволяют добавить контент до или после содержимого элемента соответственно:

div::before {
content: "До элемента";
}

div::after {
content: "После элемента";
}


У нас обязательно должно быть свойство content, а в остальном — можно использовать любые CSS правила.

Смотрите крутую статью на доке, там гораздо больше теории и других псевдоэлементов. А я рассмотрю интересный пример с прикрепленной гифки:

.btn::before {
background-color: #0A88F3;
transition: 0.3s ease-out;
}

.btn.hover-filled-slide-right::before {
top:0;
bottom: 0;
right: 0;
height: 100%;
width: 100%;
}
.btn.hover-filled-slide-right:hover::before {
width: 0%;
}


Тут вся магия реализована как раз через ::before, и это, как я считаю, самый удобный и правильный способ реализовать подобное. Мы просто анимируем параметр width, постепенно приводя его из 100% в 0% на наведение курсора. Всё гениальное просто.

Накидайте бананов 🍌, если вам нравятся посты с гифками и примерами с кодпена. Может почаще делать буду такое.

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blog#web #theory #code
🍌53👍5🔥32🐳2
Ещё один формат айдишников

Самыми популярными вариантами создания айдишников можно назвать uuid и целое положительное число:

6e522170-d7d5-494b-ae1f-5589608a6a51 // uuid.v4
4312 // целое положительное число


Лично я, среди этих двух вариантов, предпочёл бы использовать uuid, так как это наиболее безопасный и стабильный способ создавать айдишники, но у uuid есть два неоспоримых минуса: читаемость и длина.

Если на длину uuid ещё можно закрыть глаза, то вот читаемость порой просто убивает. Мне довелось поработать в проде с системой, которая содержит огромное количество разных сущностей, где каждая сущность ссылается на десяток других по ID, модели часто выглядели как набор ключ:айдишник. С целью улучшить читаемость таких идентификаторов, был сделан следующий шаблон:

<название модели>:<uuid>

примеры:

link:b386b8fd-64b6-4f49-85c0-b7292ec43713
building:364c2c5e-4cd2-4aec-b570-bb7e317ca018
office:56c5f243-b07f-450f-a6f0-18e6e363504c
user:f05db8bb-df2c-4575-b990-f87c3a8dd663
role:6fbdc403-0698-4e79-ade7-8a75dd6cd85b


Думаю, что на этих примерах идея более чем понятна. Мы просто дописывали к каждому айдишнику название сущности через знак двоеточия, соответственно дебажить и читать данные стало в разы проще. С какой-то стороны, мы увеличиваем длину айдишника, что тоже не хорошо, но рост размера payload’a, отдаваемого на UI, был мизерный, меньше 5%. Зато очень сильно улучшилась читаемость.

Таким образом, получаем самый безопасный, стабильный, читаемый айдишник. Не без минусов, конечно, но всё же, так ли он критичен?

Пост вдохновлён идеей одного из подписчиков канала, за что большое спасибо. Напоминаю, что моя личка открыта, обязательно приходите.

Спасибо за прочтение, это важно для меня ❤️

#web #data
👍33🐳8🔥42🍌1
Что такое ECMAScript?

ECMAScript, или же ECMA-262 — это стандарт скриптовых языков программирования общего назначения, который определяет синтаксис, структуры данных, правила и другие аспекты языка.

Наиболее известный пример — JavaScript, но также спецификации придерживаются языки, например, TypeScript или CoffeScript.

Спецификация ECMAScript пересматривается каждый год и версионируется двумя различными способами. На примере спецификации 2015 года, её названия — это ES6 или же ECMAScript2015. Соответственно, спецификация 2018 года будет называться ES9 и так далее.

Вообще, эта спецификация решает крайне важные задачи для развития языка и веба в целом, такие как, как не странно, стандартизация, расширяемость языка и контроль его эволюционного развития. Всё это осуществляется через систему предложений от комьюнити, где каждое предложение на изменение языка называется proposal. Подробнее о них можно прочитать в официальном гит репозитории. Также прилагаю ссылку на proposal на добавление нового глобального объекта для взаимодействия с датами, замены DateTemporal. Просто посмотреть как это выглядит, нас это изменение каснётся уже очень скоро.

Важно понимать, что в старых версиях браузеров не будут поддерживаться новые функции языка. Для решения этой проблемы существует Babel, который транспилирует код новых версий в старые, используя полифилы. Более подробно о полифилах писал в отдельном посте.

Более подробно о нововведениях каждой из версий спецификации можно почитать в отличной статье на хабре.

Также оставляю ссылку на драфт ECMAScript2025, где можно посмотреть черновики спецификации следующего года.

Такой вот пост вышел. Много ссылок, зато они очень интересные.

Спасибо за прочтение, это важно для меня ❤️

#web #theory #javascript
👍256🔥4🐳3🍌1
Preload и Prefetch

Preload и Prefetch — опции загрузки контента, которые позволяют улучшить пользовательский опыт и просто загружать все ресурсы значительно быстрее.

Preload — это механизм HTML, который позволяет вам указать браузеру загружать ресурсы (скрипты, стили, шрифты и изображения) ещё до того, как они будут использованы на странице. Это особенно полезно для ресурсов, которые будут запрошены в будущем в результате действий пользователя, таких как навигация по страницам или выполнение каких-либо действий:

<link rel="preload" href="styles.css" as="style">


В этом примере браузер будет предварительно загружать файл styles.css, как только он обнаружит этот тег <link> в HTML-документе, даже до того, как он встретит место, где эти стили используются

Prefetch — предназначен для загрузки ресурсов, которые будут использоваться на последующих страницах, а не на текущей. Он сообщает браузеру о том, какие ресурсы необходимо предварительно загрузить в фоновом режиме для улучшения скорости загрузки последующих страниц. С каким-нибудь реактом такой фокус не прокатит, однако это точно можно применять, например, со статически-генерируемыми сайтами через что-то типа 11ty.

<link rel="prefetch" href="next-page.html">


Можем просто загрузить следующую страничку в фоне и, если пользователь захочет на нее перейти, она откроется сильно быстрее.

В целом, preload и prefetch — это одни из самых базовых способов оптимизировать загрузку фронтенда, которыми точно не стоит пренебрегать. Не одним же реактом едины.

Спасибо за прочтение, это важно для меня ❤️

#web #theory
27👍14🐳3🍌1
Создание собственных ошибок в приложении

С ростом приложения может быть полезно создавать собственные ошибка для удобства их обработки, лебага и логирования. В этом посте поговорим о стандартных способах как это можно сделать.

Обычно ошибки выбрасываются следующим образом:

throw Error("Ошибка сервера")


Это удобно и быстро, но с ростом приложения можно оптимизировать и это. Для этого нужно создать собственный класс ошибки:

class CustomError extends Error {
constructor(message: string) {
super(message);
this.name = 'CustomError';
}
}


Обратите внимание, что нам нужно обязательно унаследовать собственную ошибку от стандартного класса Error и вызвать конструктор родительского класса через super — это необходимые шаги для правильной инициализации собственной ошибки. this.name устанавливается для того, чтобы ошибку в логах было проще идентифицировать. Это очень полезно, но не обязательно.

Далее разберем пример создания ошибок, которые могут возникнуть в работе с API:

class NullableRequestParameter extends Error {
constructor(message = 'Required req param is nullable') {
super(message)
this.name = 'NullableRequestParameter'
}
}

class Unauthorized extends Error {
constructor(message = 'User is unauthorized') {
super(message)
this.name = 'Unauthorized'
this.code = 401
}
}

export const RestServiceError = {
NullableRequestParameter,
Unauthorized
} as const

// где-то выбросим нужную нам ошибку
throw RestServiceError.Unauthorized()


Тут мы создаём две ошибки, которые далее сможем использовать в нашем приложении. Этап с объединением под RestServiceError можно опустить, это уже мой собственный код стайл. Люблю объединять общие сущности под единым началом.

Кстати, чтобы обработать конкретную ошибку определенным способом, используется следующая конструкция:

try {
// код, где может быть ошибка
} catch (error) {
switch (true) {
case error instanceof RestServiceError.Unauthorized:
// обработка ошибки Unauthorized
break;
case error instanceof RestServiceError.NullableRequestParameter:
// обработка ошибки NullableRequestParameter
break;
default:
// обработка всех непредвиденных ошибок
}
}


Конструкция со switch (true) является более предпочтительной из-за читаемости и расширяемости, хотя можно решить ту же задачу просто через if else.

На этом всё, что я хотел описать в этой теме. Надеюсь, что это было полезно. Поддержите реакциями)

Спасибо за прочтение, это важно для меня ❤️

#web #javascript #theory #data
26👍9🔥2🐳2🍌1
Попробуем устроить интерактив 👍

Предлагаю собрать ссылки на ваши пет-проекты. Я посмотрю их, а самые частые и популярные ошибки среди всех проектов я разберу в формате постов в этом канале

Для начала ограничимся следующим:
— открытый репозиторий на площадке типа GitHub
— проект на JavaScript/TypeScript
React или проект без использования фреймворка/библиотек

Можете поделиться постом с друзьями, участвовать могут все желающие. Анкета анонимная, но есть возможность оставить свою телегу, если хотите

Кстати, можно отправить несколько проектов на рассмотрение, для этого просто заполните форму несколько раз

🟢Google форма для участия

@prog_way_blog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍3🐳21
Схлопывание отступов CSS

Схлопывание отступов — механизм в CSS, при котором верхние и нижние внешние отступы двух соседних элементов могут объединяться в один отступ, если они расположены друг над другом. Это поведение может вызывать лишнее недопонимание.

Если рассмотреть ситуацию на фото, прикрепленное к посту, то можно увидеть два блока, верхний из которых имеет margin-bottom: 100px, а нижний — margin-top: 70px. Казалось бы, очевидно, что итоговый отступ между блоками будет 170px, но на самом деле это не так. В таком случае, отступы объединятся и будет выбрано и применено максимальное значение из двух: max(100px, 70px) => 100px.

Чтобы избежать схлопывания, достаточно использовать связку из разных отступов, например margin для верхнего элемента и padding для нижнего. Но такой способ я считаю всё таки костыльным. Гораздо лучше объединить два блока в родительский flex контейнер и использовать свойство gap для задания отступов между всеми элементами flex группы:

<div class="container">
<div>Верхний</div>
<div>Нижний</div>
</div>


.container {
display: flex;
flex-direction: column;
gap: 170px;
}


Такой способ гораздо более надёжный и контролируемый, а также читается легче.

Спасибо за прочтение, это важно для меня ❤️

#web #theory
37👍12🐳5🔥2🍌1🤝1
Метод массива with

withещё один новый метод массива из спецификации ECMAScript 2023, который позволяет удобно решить одну крайне специфичную задачу — изменить массив и создать его копию.

Если разбирать сразу же на примере, то выглядит это следующим образом:

const nums = [1, 2, 3, 4]
const newNums = nums.with(1, 'string')

console.log(newNums) // [1, 'string', 3, 4]


Первым аргументом метод with принимает индекс, на котором будет произведена замена, а вторым — новое значение.

Аналогом подобного метода можно считать прямую замену элемента при обращении по его индексу, только метод with не мутирует исходный массив:

const nums = [1, 2, 3, 4]
nums[1] = 'string'

console.log(nums) // [1, 'string', 3, 4]


Чтобы обойти мутацию, нам необходимо создавать отдельно копию изначального массива, а это неудобно. Метод with автоматически создаст копию за нас, что может сыграть на руку, например, в чистом redux.

Честно сказать, не смог придумать невероятно удобных кейсов применения этого метода, кроме редакса. На собесе ответить хватит и ладно. Есть и есть, чего бубнеть то.

#web #theory
👍37🐳10🔥31🍌1
progway — программирование, IT
Попробуем устроить интерактив 👍 Предлагаю собрать ссылки на ваши пет-проекты. Я посмотрю их, а самые частые и популярные ошибки среди всех проектов я разберу в формате постов в этом канале Для начала ограничимся следующим: — открытый репозиторий на площадке…
Было тяжело, но я справился…

Как и обещал пару постов выше, я посмотрел проекты, что вы прислали на ревью. Этим постом я закрываю сбор ссылок, их и так было не мало)

Я просмотрел абсолютно всё, что было прислано, каждый проект.

Что в итоге:
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. Не стесняйтесь создавать свои хуки, это ок. Есть примеры, где вызов 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👍104🐳4🍌1🫡1
Использование gap вместо margin

Начнем комментарии по проектам с популярной ошибки — использование margin вместо gap. Посты постараюсь делать покороче, не хочу развозить на это всю ленту.

Почему использовать gap лучше margin:
1. Легче изменять код — чаще всего отступы везде одинаковые в таких списках. При изменении отступов, проще изменить его в одном месте, чем для каждого компонента вёрстки
2. Более чистый код, отсутствие дублирования стилей
3. Лучше производительность — браузеру куда проще обработать gap в структурированной сетке, чем нарисовать для каждого отдельного элемента собственный отступ

Что такое свойство gap
Что такое row-gap, column-gap

@prog_way_blog#web #review
👍26🔥5🐳42🍌1👀1
Файловая структура проекта

Очень важно понимать, что файловая структура — это самый верный помощник разработчика в навигации по проекту.

В некоторых проектах, что прислали на ревью, в файловой структуре бывало достаточно тяжело разобраться. Тут и 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🐳62🔥2🍌1
Нейминг файлов

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, супер, круто, но видно же, что код отформатирован не по ним, а в некоторых местах вообще стоят eslint-disable комменты. Пожалуйста, помимо закидывания конфиги в проект, убедитесь, что линтер реально работает и форматирует всё так, как ожидается. Ну и eslint-disable использовать тоже очевидно не нужно)

@prog_way_blog#review
👍16🐳9🔥2🤯2🍌1
Комплексные состояния

Есть такой код:

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
Магические числа

Немного магии — не всегда приятно. Есть код:

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🐳32🔥2🍌2🗿2
2025/07/10 15:46:11
Back to Top
HTML Embed Code: