Chulakov Dev – Telegram
Chulakov Dev
1.16K subscribers
139 photos
5 videos
204 links
Канал команды разработки Студии Олега Чулакова.

Советы по Frontend- и Backend-разработке web-сервисов, мобильных приложений, статьи и презентации от наших разработчиков, анонсы проектов и многое другое.

Обсудить проект @YuraAndreev
Download Telegram
Всем привет!

На рынке веб-разработки существует множество CMS с готовой административной панелью и набором базовых функций, таких как WordPress, 1C-Bitrix, Joomla и другие.

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

Одной из популярных Headless CMS с открытым исходным кодом является Strapi. Сегодня мы соберем свой образ для использования в проектах.

👉🏻 Читать пошаговую инструкцию

@chulakov_dev
🔥22👍43
Всем привет!

При разработке frontend-приложений важно учитывать ситуации, когда данные от backend еще не доступны. React Query и его хук useQuery предлагают инструменты для управления этим процессом.

Один из ключевых параметров, на который следует обратить внимание, — isLoading. Он показывает, выполняется ли запрос данных. Если обратиться к data без проверки isLoading, это может вызвать ошибку, так как данные могут быть еще недоступны.

const { isLoading, error, data } = useQuery('myData', fetchData);

Правильное использование isLoading включает проверку его значения перед применением данных, как показано в примере:

function MyComponent() {
const { isLoading, error, data } = useQuery('myData', fetchData);

if (isLoading) return 'Загрузка...';
if (error) return `Произошла ошибка: ${error.message}`;

return (
<div>
<h1>{data.noscript}</h1>
<p>{data.denoscription}</p>
</div>
);
}

Здесь, если isLoading = true, компонент просто отображает сообщение «Загрузка...», а использование данных начинается только после их успешной загрузки.

Вы можете думать, что проверка isLoading не всегда необходима и в некоторых случаях можно использовать опциональную цепочку (optional chaining). Однако это может быть опасно. Если данные еще не получены, а мы пытаемся передать их в компонент, ожидающий конкретные данные, это может привести к ошибке. Вот пример:

function MyOtherComponent({ noscript, denoscription }) {
return (
<div>
<h1>{noscript}</h1>
<p>{denoscription}</p>
</div>
);
}

function MyComponent() {
const { data } = useQuery('myData', fetchData);

return (
<MyOtherComponent noscript={data?.noscript} denoscription={data?.denoscription} />
);
}

В этом случае, если данные еще не получены, опциональная цепочка вернет undefined для data?.noscript и data?.denoscription, что может вызвать ошибку в MyOtherComponent.

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

@chulakov_dev
🔥17👍53🤔2
Привет!

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

Итак, внимание, вопрос! 👇🏻
👍10🔥4🤔3
Как добавить изменения в последний коммит, не создавая новый и не изменяя его описания?
Anonymous Quiz
5%
git commit --current-message
3%
git commit -t
69%
git commit --amend --no-edit
23%
git commit --amend -m false
🔥108👍6🤯1
Всем привет!

Многие из вас наверняка знают про метод stopPropagation. Он связан с таким понятием, как event bubbling, а сам он останавливает действие всплытия/погружения наступившего события.

Но (для нас это не было неожиданностью) почти никто не знает о его брате — методе stopImmediatePropagation. Он используется намного реже stopPropagation, но знать о нем нужно и важно.

Метод stopImmediatePropagation останавливает все всплытия/погружения всех событий на определенном HTML-элементе. Допустим, если один элемент регистрирует у себя несколько событий, например от нескольких дочерних элементов, и они все начинают всплывать, то метод stopPropagation остановит только один из них, а stopImmediatePropagation — все.

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

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥54
Всем привет!

Сегодня хотим рассказать интересный факт о скорости разных циклов. Вы знали, что forEach работает быстрее обычного for в 2–4 раза?

Вот доказательство:
const arr = new Array(10000).fill(0).map((_, i) => i);

function forFn() {
let res;

for (let i = 0; i < arr; i++) res = arr[i];
}

function forEachFn() {
let res;

arr.forEach(item => res = item);
}

function calculateLoopTime(callback) {
const time = performance.now();
callback();

console.log(performance.now() - time);
}

calculateLoopTime(forFn); // от 0.3s до 0.7s
calculateLoopTime(forEachFn); // от 0 до 0.3s

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

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

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥73
Привет, друзья!

Сегодня мы коснемся важной темы: как правильно использовать key при рендеринге списков в React.

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

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

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

Как же решить эту проблему и обезопасить себя?

Используйте уникальные ID в качестве ключей. Если данные приходят с бэкенда, они, вероятно, уже имеют ID. На клиентской стороне вы можете указать сами уникальные идентификаторы или использовать библиотеку Nanoid для генерации, но делать это нужно не в момент рендера, а при определении массива. Кстати, по этой же причине и не рекомендуется применять метод Date.now().

Может показаться, что использовать Date.now() в качестве уникального ID — это быстрый и простой способ. Но здесь скрыта уязвимость: если вы попытаетесь создать два элемента одновременно, получите два одинаковых ID. Поэтому вместо поиска быстрых решений лучше довериться проверенным инструментам и способам.

😕 Вы могли заметить, что мы не упомянули хук useId. Дело в том, что такие идентификаторы будут уникальны только в рамках компонента, а нам нужны ID, которые уникальны глобально в рамках всего приложения.

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

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥173👍1
Друзья, привет!

Давайте устроим разминку для мозгов! На картинке задача, которую мы предлагаем вам решить.

Ниже выбирайте свой вариант ответа👇🏻
👍8🔥51
Что будет выведено в консоль?
Anonymous Quiz
38%
Hi!
40%
Hello!
8%
undefined
14%
Будет ошибка
👍10🔥7😢2
Привет!

В системе типов TypeScript есть группа, которая называется гомоморфной, т.е. типы, которые изменяют функциональность, сохраняя первоначальные свойства применяемой сущности. В этой группе есть четыре типа: Readonly, Partial, Required, Pick.

Readonly
— добавляет каждому свойству/методу объекта модификатор readonly, т.е. делает их доступными только для чтения.

type User = {
name?: string;
}

type ReadonlyUser = Readonly<User> // { readonly name?: string; }

const user: ReadonlyUser = {
name: 'Jack'
}

// Cannot assign to 'name' because it is a read-only property.
user.name = 'John'

Обратите внимание на знак вопроса у свойства name. Мы намеренно сделали его необязательным, но Readonly оставит его таковым, так как, являясь гомоморфным, он не изменяет остальные модификаторы.

Partial добавляет всем свойствам/методам модификатор ?, делая их необязательными.

type User = {
readonly name: string;
age: number;
};

type OptionalUser = Partial<User>; // { readonly name?: string; age?: number; }

const user: OptionalUser = {}; // Ok!

Required противоположен Partial. Он превращает члены объекта в обязательные, удаляя модификатор ?.

type User = {
readonly name?: string;
age?: number;
};

type RequiredUser = Required<User>; // { readonly name: string; age: number; }

/**
* Type '{}' is missing the following properties
* from type 'Required<User>': name, age
*/
const user: RequiredUser = {}

И последний — Pick. Фильтрует объектный тип по свойствам/методам и формирует из него новый тип. Если вы знаете, как работает тип Omit, то это противоположная ему процедура. Первый дженерик принимает в себя фильтруемый тип, а второй — перечисление свойств/методов, которые требуется отфильтровать (перечисляются через оператор | ):

type User = {
readonly name: string;
age: number;
height: number;
};

// { readonly name: string; age: number; }
type PickUser = Pick<User, 'name' | 'age'>;

const user: PickUser = {
name: 'Jack'
}

// Cannot assign to 'name' because it is a read-only property.
user.name = 'John'
👍16🔥52
Всем привет!

Недавно у нас был пост с инструкцией, как создать свой образ Strapi. Сегодня мы расскажем, как настроить окружение для его дальнейшего использования в Docker.

👉🏻 Читать инструкцию

@chulakov_dev
🔥12👍54
Друзья, привет!

➡️ Сегодня поговорим про замечательную функцию от Next.js — Incremental Static Regeneration (ISR) — и про то, как ревалидировать данные на уровне страницы по таймеру. Тема актуальна для всех, кто использует версию Next.js >= 12.4.

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

↪️ По сути, это комбинация из лучшего, что есть у SSR/RSC и SSG, которая работает следующим образом:
— при первом запросе к странице отдается кешированная версия из сборки;
— затем в фоновом режиме запускается повторная генерация страницы через вызов getStaticProps;
— если генерация прошла успешно, обновленная версия попадает в кеш;
— при ошибке продолжит отдаваться предыдущая версия из кеша;
— так достигается отказоустойчивость;
— кеширование происходит локально на сервере, на Vercel кеш глобальный и автоматически распределяется (об этом сегодня не будем говорить).

Управлять ISR можно так:
— частоту обновления задать через revalidate в секундах в getStaticProps;
— принудительно очистить кеш через API-метод revalidate;
— On-demand revalidation при обновлении данных.

// пример использования

export const getStaticProps = async () => {

return {
props,
revalidate: 10, // ревалидировать каждые 10 секунд
}


}


// On-demand
await res.revalidate('/some-page')

Таким образом, ISR позволяет оптимально сочетать скорость статической генерации и гибкость обновления данных. Рекомендуем для сайтов с часто меняющимся контентом!

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥174👍4
Всем привет!

В новой статье на Хабре мы разобрали основные особенности языка Kotlin. Рассмотрели такие важные аспекты, как безопасность работы с null-значениями, гибкость типизации с помощью Generics, возможности расширения функциональности с помощью extension-функций, inline-функции и многое другое.

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

➡️Читайте и подписывайтесь на наш блог.

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍43
Мы все долго ждали этого момента — выхода нового большого интервью Олега Чулакова.

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

Кто еще не смотрел, держите ссылку на интервью. Приятного просмотра.

@chulakov_dev
🔥133🐳32
Всем привет!

Готовы проверить свои знания по команде git push?

Ниже вопрос и варианты ответов👇🏻
❤‍🔥7🔥1
Мы создали в локальном репозитории ссылку на другой удаленный репозиторий (git remote add github-repo ...). Как сделать в него пуш, чтобы скопировать все содержимое репозитория (ветки, теги, коммиты и т.д.)?
Anonymous Quiz
4%
git push github-repo
18%
git push --clone github-repo
54%
git push -u origin github-repo
25%
git push --mirror github-repo
🔥13👍53
Привет, друзья!

Мы собрали ТОП-5 книг по JavaScript для тех, кто только собирается погрузиться в изучение этого языка.

📔 «Изучаем программирование на JavaScript», Э. Фримен, Э. Робсон

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

📔 «Современный учебник JavaScript», И. Кантор

Самое популярное онлайн-издание по JavaScript в русском сегменте. В учебнике объясняется не только JS, но и то, как работает DOM, браузер, а также раскрываются другие важные темы. Идеальная вторая книга.

📔 «JavaScript: подробное руководство», Д. Флэнаган

Самая фундаментальная книга по JavaScript из когда-либо написанных. Осилив ее внушительный объем, можно в полной мере стать сенсеем.

📔 «Как устроен JavaScript», Д. Крокфорд

Небольшая, но емкая книга от создателя JSON. Автор понятно объясняет базовые вещи. При этом опытные senior-разработчики тоже найдут в ней что-то новое для себя.

📔 «Элегантный JavaScript», М. Хавербеке

Пожалуй, самая сложная, но и самая интересная книга по основам JavaScript. Внутри вы найдете задание по созданию своего языка программирования, которое обязательно стоит выполнить.

А вы читали эти книги? Поделитесь своей подборкой любимых изданий.

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👌4🤩32
Привет!

Давайте разберем принцип работы async/await под капотом. Посмотрим, как выполняется код с обычной и асинхронной функцией — это поможет понять, почему async/await ведет себя именно так, — и разберем, почему происходит неблокирующее ожидание.

Читать про async/await

@chulakov_dev
🔥20👍31🤔1
Привет!

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

CrossConf
15.09 — Москва
Ежегодная конференция по кросс-платформенной разработке и трендам IT. После докладов желающие смогут продолжить общение с коллегами на afterparty.

Стачка
15–16.09
— Ульяновск
Десятая по счету международная IT-конференция. Темы выступлений охватят несколько разных направлений — от разработки до продаж.

FrontendConf
02–03.10
— Москва
Cамая масштабная конференция по frontend-разработке в России. Своим опытом поделятся ведущие разработчики из крупнейших IT-компаний.

Joker
09–10.10 — online
13–14.10 — Санкт-Петербург и online
Одна из старейших конференций для Java‑разработчиков. Здесь можно узнать практическую информацию об использовании Spring Boot и разобраться, как JVM работает «под капотом».

Heisenbug
10–11.10 — online
15–16.10 — Санкт-Петербург и online
Крупнейшая в России конференция по тестированию ПО. Ожидаются доклады для специалистов разных профилей: QA-инженеров, разработчиков, тимлидов, директоров по качеству и др.

Mobius
01–02.11 — online
09–10.11 — Санкт-Петербург и online
Конференция для специалистов, связанных с мобильной разработкой: iOS- и Android-разработчиков, архитекторов мобильных приложений, специалистов по DevOps и др.

HolyJS
02–03.11 — online
11–12.11 — Санкт-Петербург и online
Конференция для JavaScript‑разработчиков. JS‑разработку здесь рассматривают в разных ракурсах — от конкретных фреймворков до борьбы с техдолгом.

PiterPy
07.11 — online
13–14.11 — Санкт-Петербург и online
Конференция для тех, кто пишет на Python и использует его в работе.

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

TeamLead Conf
30.11–01.12
— Москва
Профессиональная конференция только для тимлидов.

@chulakov_dev
👍155🔥1
Всем привет!

В работе с React каждый разработчик сталкивается с механизмом batching. Знаете ли вы, что это такое?

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

Рассмотрим пример:

export default function App() { 
const [username, setUsername] = useState("JohnDoe"); const [followers, setFollowers] = useState(1000);
const handleClear = () => {
setFollowers(0); setUsername("");
}
useEffect(() => { console.log("Компонент был отрендерен!");
});
return ( /* JSX код */ );
}

Казалось бы, при нажатии на кнопку clear компонент должен перерисоваться дважды из-за двух изменений состояния. Но благодаря batching в логах вы увидите лишь одно сообщение: «Компонент был отрендерен!»

Почему так происходит? React группирует несколько изменений состояния, вызванных последовательно, в одно обновление, выполняя всего одну перерисовку.

Для приложений с частыми обновлениями состояния этот механизм становится настоящим спасением, обеспечивая плавность и отзывчивость интерфейса.

Но бывают ситуации, когда нам такое поведение не подходит. В этом случае React предоставляет метод с именем flushSync() в react-dom, который позволяет нам инициировать повторный рендеринг для определенного обновления состояния.

const handleClick = () => {
flushSync(() => { setClicked(!clicked);
// react will create a re-render here });
setCount(count + 1);
// react will create a re-render here};

Но flushSync() стоит использовать осторожно, так как он может значительно снизить производительность.

@chulakov_dev
🔥22👍61
Привет, друзья!

Предлагаем пошевелить мозгами и решить задачу на картинке.

Ниже выбирайте свой вариант ответа👇🏻
👍8