Maxim WebDev
513 subscribers
36 photos
8 videos
39 links
Здесь узнаешь, как проходить собеседования Front-End разрабу на СНГ рынке

- Я Senior Front-End, делюсь с тобой личным опытом в IT
- Рассказываю про лайфхаки в прохождении собесов
- Показываю примеры задач с моих job-интервью

My Contact: t.me/max_webdev
Download Telegram
На моем YouTube вышло новое видео! 🔥 Посмотреть его можно здесь.

Создаем NPM библиотеку UI компонентов. React, Typescript, Storybook. Публикуем на GitHub Packages

————————————

Вот полезные материалы и упоминания из ролика:

1. В видео в dependencies мы установили только react и данная библиотека не попадает в итоговый билд (в папку dist), благодаря параметру external.
Скорее всего, у вас в библиотеке будут использоваться и другие npm-модули (например, lodash). И чтобы эти модули попадали в билд, вам необходимо установить пакет @rollup/plugin-node-resolve. Также в нем можно указать либо исключить конкретные модули для папки dist при помощи параметра resolveOnly.
2. Начальный код. Склониуйте его себе, если будете разрабатывать библиотеку вместе со мной по видео. tsconfig, eslintrc и другие конфиги также смотрите по этой ссылке);
3. Настройка webpack для storybook;
4. Команда для установки wepback5 модулей:

npm install @storybook/builder-webpack5 @storybook/manager-webpack5 -D

5. Шаблон для файла .npmrc:

registry=https://registry.npmjs.org/
@YOUR_GITHUB_USERNAME:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=YOUR_AUTH_TOKEN


6. Шаблон названия библиотеки для файла package.json:

"name": "@YOUR_GITHUB_USERNAME/YOUR_REPOSITORY_NAME",
"publishConfig": {
"registry": "https://npm.pkg.github.com/YOUR_GITHUB_USERNAME"
},


7. Необходимые зависимости storybook для работы контролов:

"@storybook/addon-essentials": "^6.5.13",
"@storybook/addon-interactions": "^6.5.13",
"@storybook/addon-links": "^6.5.13",


8. Начальные зависимости в package.json.
9. Репозиторий с итоговым кодом.
❤1
Когда применять React.memo? Оптимизации в React

В общем и целом, React быстрый, если придерживаться его best practices и в нужных местах применять оптимизации при помощи React.memo.

Хочу поговорить про этот React.memo, потому что штука очень важная и я ее в последнее время часто применяю. Если кто не знает, то React.memo автоматически проверяет, изменились ли пропсы. И если они не изменились, то React не вызовет ререндер и вернет результат прошлого рендера.

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

1. Первым делом нужно посмотреть, можете ли вы вынести состояние в другую компоненту или разбить основную компоненту на подкомпоненты.
2. Если после того, как вы разбили компоненты, у вас проблема с лишними ререндерами не решилась (либо решилась частично), то стоит применить React.memo.

Тут нужно помнить, что если вы оборачиваете компоненту в React.memo, то обязательно стоит смотреть на тип данных пропсов. Если все пропсы примитивы, то оборачиваем спокойно.

Если какие-то пропсы являются объектами и (или) функциями, то значения этих пропсов необходимо обернуть в useMemo и useCallback соответственно. Если вы этого не сделаете, то React.memo уже не будет выполнять свою главную функцию. Конечно, если ваше значение имеет тип данных объект и хранится в useState, то ничего в useMemo оборачивать не нужно.

А вы используете React.memo в своем коде? 😏
👍9
В последние полгода я работаю только из дома. Все время сидеть в квартире за ноутом довольно трудно, поэтому вечером либо в обед я прогуливаюсь до кофейни и работаю оттуда.

Кстати, это довольно удобно и очень даже атмосферно ☕️

А вы в каком месте в основном работаете? 😏
👍5
Монтируется новый видос на YouTube. Выйдет в воскресенье (сегодня) либо в начале следующей недели. 😉

Наконец-то добрались руки до 3-й части видео про верстку (адаптив) 🔥

Плейлист по версте макета на HTML и SCSS можно найти здесь.
👍6❤‍🔥2🔥2
Всем привет! На моем YouTube вышло новое видео 🔥

Адаптивная верстка сайта c нуля для начинающих | HTML и SCSS (SASS)

Посмотреть можно здесь 👈

————————————

Вот полезные материалы и упоминания из ролика:

1. Конечный код на GitHub.
2. Начальный код на GitHub.
3. Макет из Figma.
4. Файл mixins.scss с миксинами для создания media запросов.
5. Единица измерения rem.
6. Использование миксинов в SASS (SCSS)
🔥8
На моем YouTube 1000 подписчиков 🥳 Всем спасибо!

P.S. Но монетизации все равно не будет 🥲
🔥1
Более крутая альтернатива Storybook?

Недавно нашел инструмент, который может заменить Storybook во многих React-проектах. Этот инструмент называется @ladle/react.

Меня всегда напрягал Storybook следующими вещами:

1. Долгий релоуд стори после внесения изменений в код;
2. Долгая сборка билда всех сторей;
3. Куча лишнего кода, который требуется для написания стори.

Как говорится в документации ladle: "Ladle is almost 20x smaller" (имется в виду билд почти в 20 раз меньше, чем у Storybook).

Я попробовал переписать наш текущий Storybook на проекте на @ladle/react. Всего примерно было 30 сторей. Вот результат, который я заметил:

1. Релоуд стори работает намного быстрее после внесения изменений в код.
2. Размер итогового билда всех сторей от Ladle составляет 1.8 мб, у Storybook - 13.0 мб. В 7 раз меньше! Конечно не в 20, но тоже много.
3. Количество строк кода в файлах сторей уменьшилось на 10-40%. Это дает понять, что в Storybook есть много шаблонного кода, который обязателен для его работы.
4. Да и как по мне, настроить Ladle намного проще и ему не нужно куча дополнительный пакетов, как storybook.

Как-то так, буду теперь предлагать на проекте убрать Storybook и внедрить Ladle 😄
❤5🔥1
Как безопасно отрендерить HTML-строку в React? dangerouslySetInnerHTML

Всем привет! Хочу поделиться своим опытом использования dangerouslySetInnerHTML. На моем текущем проекте бэкендеры решили, что грамотно возвращать HTML-строку в запросах. Вот пример того, какая строка может прийти "Click <a href="/link" >here</a>".

Так вот, эту HTML-строку нужно правильно отрендерить в React. И при том чтобы не было дыр в безопасности, так как мы знаем, что в HTML-строку можно вставить вредоносный код.

Если у вас есть HTML-строка, и вам ее нужно отрендерить в React, то правильным выбором будет использовать атрибут dangerouslySetInnerHTML. Как говорится в самой доке React:

"dangerouslySetInnerHTML is React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack".

Чтобы не подвергать свой код риску вредоносного скрипта при использовании dangerouslySetInnerHTML, можно использовать библиотеку DOMPurify. После ее внедрения, ваш код будет выглядеть следующим образом.

<span dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(htmlString)}} />

————————————

P.S. Я сделал для вас пример переиспользуемой компоненты, которую можно юзать для рендера HTML-строки в React. Можете потыкать компоненту по ссылке.

Вообще, подключение библиотеки для решения только одной небольшой проблемы - это не самый лучший вариант. Но пока что другого выхода я не нашел. В Browser API уже появился метод setHTML, который решает эту задачу с безопасностью innerHTML и dangerouslySetInnerHTML. Но этот метод еще в статусе Experimental.

Поэтому рассмотренный выше вариант кода является неплохим решением.
🔥9
Проблема с useMutation в react-query

На проекте мы используем react-query и совсем недавно я заметил необычную особенность в хуке useMutation. Проблема в том, что при повторном вызове mutateAsync, параметр data у мутации сначала изменяется на undefined, а затем уже на значение, которое пришло из запроса.

И если смотреть на это при изменении в UI, то получается "скачущий" текст, что конечно же является не самым правильным поведением для пользователя. Получается примерно так:
"data при 1-м запросе" --> undefined --> "data при 2-м запросе" --> undefined --> ""data при 3-м запросе" и т.д.

Я перекопал в интернете много вариантов, почему useMutation так работает, и как пофиксить это поведение, но ничего не нашел.

Поэтому я придумал написать кастомный хук useMutationState, который решил эту задачу. Потыкать его можно в Codesandbox по ссылке.

————————————

P.S. Если у вас есть решение получше, чем мой кастомный хук useMutationState, то оставляйте предложения в комментариях 😉
👍7
Господа программисты, мне от вас нужно инженерное решение. Я уже обсуждал варианты решения с друзьями из IT, пока нет ничего на 100% рабочего.

Проблема: бомжи терроризируют район Маяк Минска (это НЕ шутка!). Сейчас все мусорные баки закрыты в беседках из железных листов. На каждой беседке есть дверь с кодом. Код 2-значный и нужно вводить цифры на замке одновременно.

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

Задача: необходимо придумать решение, благодаря которому бомжи бы не ходили по району с целью опустошения мусорок.

Уже предложенные варианты:
1. Беседки с мусорными баками будут открываться при помощи чипа. Но проблема в том, что если бомжу в руки попадется чип, то вся система «защиты» рухнет.
2. Вызвать несколько раз милицию, чтобы они разогнали бомжей. Это чересчур легко, нам нужно инженерное решение!

А КАКИЕ У ВАС ПРЕДЛОЖЕНИЯ, ГОСПОДА?

P.S. Я уважаю всех людей, в том числе бездомных, но проблему нужно решать.
😱2
Кратко покажу мои последние диалоги в LinkedIn.

М: Здравствуйте, мне интересна ваша вакансия. Она все еще актуальна?
Р: Добрый день, Максим! Да, актуальна.
М: Подскажите вилку ЗП по вакансии?
Р: Знаете, мы отталкиваемся от ожиданий кандидата. Какие у вас ожидания?
М: N$ чистыми в месяц. Вам подходят такие условия?
Р: Ой нет, это много для нас, мы можем дать максимум X$.

Неужто они надеются найти тех, кто попросит гораздо меньше от их максимальной вилки? 🤔
🤡6🤷‍♂1😁1
✌️React Fiber для собеседований

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

Fiber это...

Fiber – переделанная реализация алгоритма Reconciliation.

Ключевые задачи Fiber:

1. Возможность разбивать работу по рендерингу на фрагменты (чанки) и распределять данную работу по нескольким кадрам.
2. Возможность прерывать, приостанавливать или повторно использовать обновления (работу) по мере поступления новых обновлений.
3. Возможность задавать приоритет конкретным обновлениям.

Fiber Call Stack

Fiber переделывает поведение обычного Call Stack. Единицу Fiber можно рассматривать как элемент стека (либо единицу работы).

Главное преимущество Fiber Call Stack в том, что он может хранить элементы стека в памяти и исполнять эти элементы (выполнять работу) когда это необходимо, то есть Fiber Call Stack может планировать выполнение задач (scheduling). А обычный JS Call Stack так не может, он будет продолжать выполнять работу до тех пор, пока стек не опустеет.

Полезные ссылки:

1. React Fiber Architecture
2. Подробно о React Reconciliation, или Как React добился 60 fps

P.S. В следующем посте расскажу про структуру Fiber-объекта (type, key, pendingProps, memoizedProps, pendingWorkPriority и др)
👍15
✌️Структура Fiber

Ссылка на 1-ю часть про React Fiber.

Единицу Fiber можно рассматривать как элемент стека, но можно и как экземпляр компоненты. И у данной компоненты (объекта) есть несколько ключевых полей.

1. type - тип компоненты. Для обычных компонент как HTML-элементов это строка ('div', 'span' и др). Для кастомных компонент (<MyComponent /> например) type - это функция или класс.

2. key - ключ компоненты, нужен, чтобы определить, необходимо ли переиспользовать компоненту. Часто key используется при рендере списков.

3. child - это то, что возвращает компонента для рендера. В примере ниже в параметре child будет храниться MyChild.

function Parent() {
return <
MyChild />
}


4. return - это Fiber элемент, к которому должна вернуться программа после обработки текущего Fiber элемента.

Из примера кода выше значением return для MyChild будет Parent.

5. pendingProps и memoizedProps - pendingProps это пропсы в начале выполнения, memoizedProps - пропсы в конце выполнения. Если данные пропсы равны, то это знак для алгоритма React, что предыдущее возвращаемое значение можно переиспользовать. А это значит, что нет необходимости в ререндере.

6. pendingWorkPriority - это число, которое обозначает приоритет единицы работы (задачи для выполнения). Чем больше число, тем ниже приоритет (всего 6 приоритетов).

Алгоритм React использует pendingWorkPriority для поиска следующей единицы работы, которую необходимо выполнить.

P.S. Это конечно же не весь список, но для базового понимания хватит.
👍9
В общем и целом, получил отказ на собеседовании. Ответ довольно частый и типичный «мы сделали выбор в пользу другого кандидата».

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

Не сконектились получается, да и много денег попросил))

А вы как часто получаете отказ в формате «мы выбрали другого кандидата»?
❤10😁1
✌️Минусы React

Я уже больше 4 лет пишу на React и поэтому могу выделить несколько его минусов. При этом я немного писал на Vue, поэтому есть с чем сравнить.

1. Это библиотека и поэтому большинство разработчиков пишут на React как хотят. Многие не задумываются по поводу архитектуры, как разделять бизнес логику и UI, поэтому всё пихают внутрь компонент. Если в команде нет правил и ограничений по архитектуре, то каждый будет писать, как хочет.

2. useContext. У данного хука нет мемоизации селекторов и поэтому если делать большой объект с данными, то это будет вести к большому количеству ненужных апдейтов.

Часто на проектах я вижу, как делают один большой объект с данными для одной страницы (а иногда для всего приложения) и передают все это в контекст. При этом значение контекста довольно часто обновляется и используется в разных частях проекта. Конечно же, такой способ не самый оптимальный.

Если хотите больше подробностей и реальных примеров из кода про пункт 3, то наставьте 🔥 под этот пост.

3. Нужно много думать о том, как построить свое дерево компонент, чтобы предотвратить лишние ререндеры и сделать само дерево максимально оптимизированным при апдейтах. Почему разработчик должен об этом думать? Разве не проще делегировать эту задачу самой библиотеке?

4. React заставляет много думать об объектах как о ссылках. Особенно это связано с передачей объектов (или функций) в deps и пропы мемоизированной компоненты.

Допустим моя компонента обернута в memo и она принимает в себя проп-функцию. Тогда мне эту функцию нужно обернуть в useCallback, а чтобы это понять, необходимо лезть в компоненту. А я ведь могу забыть про это, что моя компонента мемоизирована. В общем, это очень большая сложность.

5. Бывают моменты, когда очень много зависимостей в useEffect, useMemo либо useCallback. Разработчику приходится следить, не забыл ли он добавить какую-либо зависимость, не забыл ли он удалить лишнюю зависимость.

А вы согласны со всеми 5-ю минусами React? Может у вас есть что добавить?)

Полезные ссылки

1. Кто не понял пункт 4, то почитайте мой пост “Когда применять React.memo? Оптимизации в React”
2. useContext в React
3. React Fiber для собеседований
4. How the useEffect Hook Works
🔥21👍1
Еще одно напоминание, почему я не откликаюсь на вакансии на rabota.by либо hh.ru.

Чаще всего сам сайт автоматически присылает отказ. Навряд ли на втором скриншоте мне ответил сам рекрутер, потому что такое шаблонное сообщение получаю уже не в первый раз.

Я лично ищу вакансии на hh.ru, но откликаюсь все равно через LinkedIn. Подробнее о том, как я это делаю через LinkedIn можно почитать здесь.
❤4
✌️Главный минус useContext и как с ним справиться

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

Я для вас сделал пример кода, по которому можно понять ключевую проблему useContext. Чтобы его посмотреть перейдите в CodeSandbox (с телефона тоже можно потыкать пример). В примере есть контекст CounterContext, который управляет двумя состояниями count1 и count2. Дело в том, что состояния не зависят друг от друга и используются в разных компонентах (count1 в Count1Component, count2 в Count2Component).

В примере нажмите на кнопку "increment count1". Вы сразу же увидите, что состояние обновилось и изменения отобразились на экране. Но дело в том, что изменение состояния в Count1Component ведет к ререндеру компоненты Count2Component (обратите внимание на параметр Renders amount). Хотя казалось бы, зачем обновлять другую компоненту, когда обновление интерфейса происходит в совсем другой части приложения?

В этом и состоит главная проблема контекста. И для ее решения один из разработчиков React Дэн Абрамов предлагает 3 варианта решения:

1. Разделить один контекст на два контекста.
2. Сделать вместо одной компоненты две: одна использует useContext, вторая обернута в memo и предотвращает лишние ререндеры из-за useContext.
3. Оставить одну компоненту, но весь JSX обернуть в useMemo и в качестве deps передать значения из контекста.

Более подробно про эти 3 пункта со всеми примерами кода можно ознакомиться здесь.

Честно говоря, я на практике использовал только 1-й вариант. Все остальные как-то не доводилось, да и большого смысла я в этом не видел. Все-таки я считаю, что контекст нужно использовать в правильном назначении, а 2 и 3 варианты больше исправляют неправильно применение useContext в проекте.

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

- Изменение темы со светлой на темную для всего приложения;
- Получение с бэка настроек и параметров для конкретной страницы. При чем эти параметры используются глубоко в дереве компонент и не очень удобно их передавать через пропсы. Главное, чтобы ваши полученные с бэка настройки не часто обновлялись;
- Управление тостами;
- и другое...
❤4👍1🔥1👏1
Хочу поделиться с вами некоторыми задачами, которые давили мне на последних собеседованиях. Позиция Middle+ / Senior 🔥. Они в принципе довольно простые, поэтому можете проверить свои знания. Я предлагаю вам не запускать код, а попробовать самим сначала решить.

Напишите потом в комментариях к этому посту, сколько вы решили задач. Я лично решил 2 из 3 :)) Вот что бывает, если не повторять базу перед собесами.

1. Задача на контекст this. Что будет выведено в консоль? Как исправить данный пример, чтобы он корректно работал?

const database = {
filterId: 'active',
users: [
{
id: 'active',
label: 'Active',
},
{
id: 'inactive',
label: 'Inactive',
},
],
getUsers: function() {
return this.users.filter(function (user) {
return user.id === this.filterId
})
}
}

console.log(database.getUsers())

2. Задача на hoisting. Что будет выведено в консоль?

(function () {
f()

f = function() {
console.log(1)
}
})()

function f() {
console.log(2)
}

f()


3. Задача на event loop. Что будет выведено в консоль? Будет ли блокироваться UI в таком случае?

sleep(2000).then(() => {
console.log(0)
})

console.log(1)

setTimeout(() => {
console.log(2)
})

function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}

console.log(5)

function myPromise() {
abc().then((val) => {
console.log(val)
return myPromise()
})
}

function abc() {
return new Promise((resolve) => {
resolve(6)
})
}

myPromise()
❤6👍4🔥2