TGViewer
Channel Public Channel
Deep Digital

Deep Digital

@deepdigital

Разработка цифровых продуктов на современных технологиях и фреймворках.

Обсудить проект @YuraAndreev
Subscribers
1.06K
Photos
140
Videos
7
Links
207

Showing posts older than #315 · Back to latest

Older Posts 20 shown
Post #314 667
  • 🔥 13
  • 👍 5
  • ❤ 3
Post #313 646
Всем привет!

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

Ниже вопрос и варианты ответов👇🏻
  • ❤‍🔥 7
  • 🔥 1
Post #312 643
Мы все долго ждали этого момента — выхода нового большого интервью Олега Чулакова.

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

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

@chulakov_dev
  • 🔥 13
  • ⚡ 3
  • 🐳 3
  • ❤ 2
Post #311 636
Всем привет!

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

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

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

@chulakov_dev
  • 🔥 12
  • 👍 4
  • ❤ 3
Post #310 614
Друзья, привет!

➡️ Сегодня поговорим про замечательную функцию от 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
  • 🔥 17
  • ⚡ 4
  • 👍 4
Post #309 639
Всем привет!

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

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

@chulakov_dev
  • 🔥 12
  • 👍 5
  • ❤ 4
Post #308 658
Привет!

В системе типов 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
  • 🔥 5
  • ⚡ 2
Post #307 583
  • 👍 10
  • 🔥 7
  • 😢 2
Post #306 599
Друзья, привет!

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

Ниже выбирайте свой вариант ответа👇🏻
  • 👍 8
  • 🔥 5
  • ❤ 1
Post #305 595
Привет, друзья!

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

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

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

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

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

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

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

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

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

@chulakov_dev
  • 🔥 17
  • ❤ 3
  • 👍 1
Post #304 557
Всем привет!

Сегодня хотим рассказать интересный факт о скорости разных циклов. Вы знали, что 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
  • 👍 16
  • 🔥 7
  • ❤ 3
Post #303 627
Всем привет!

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

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

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

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

@chulakov_dev
  • 👍 14
  • 🔥 5
  • ❤ 4
Post #302 583
  • 🔥 10
  • ❤ 8
  • 👍 6
  • 🤯 1
Post #301 576
Привет!

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

Итак, внимание, вопрос! 👇🏻
  • 👍 10
  • 🔥 4
  • 🤔 3
Post #300 598
Всем привет!

При разработке 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.title}</h1>
<p>{data.description}</p>
</div>
);
}

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

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

function MyOtherComponent({ title, description }) {
return (
<div>
<h1>{title}</h1>
<p>{description}</p>
</div>
);
}

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

return (
<MyOtherComponent title={data?.title} description={data?.description} />
);
}

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

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

@chulakov_dev
  • 🔥 17
  • 👍 5
  • ❤ 3
  • 🤔 2
Post #299 676
Всем привет!

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

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

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

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

@chulakov_dev
  • 🔥 22
  • 👍 4
  • ❤ 3
Post #298 598
Привет, друзья!

🤔 Интересно, вы когда-нибудь слышали о методе requestIdleCallback?

Сегодня поговорим о нем.

⚫️Метод requestIdleCallback очень редко используется, но в некоторых моментах он может значительно оптимизировать ваш код. Его суть заключается в следующем: метод принимает в качестве первого аргумента колбэк, который ставит в очередь Task Queue, и этот колбэк выполняется, когда браузер находится в режиме простоя.

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

⚫️Вторым аргументом он принимает дополнительные параметры, но пока реализован только один — timeout. В нем вы можете указать максимальное время (в миллисекундах), которое потребуется колбэку на выполнение. Если он не уложится в отведенное вами время, выполнение колбэка прервется.

Этот метод пока не поддерживается в Safari, но мы надеемся, что специалисты из Apple вскоре реализуют такую классную возможность.

@chulakov_dev
  • 👍 20
  • ❤ 4
  • 🔥 4
Post #297 651
Всем привет!

Давайте разберем вчерашний вопрос «Какой функциональный объект в JS можно назвать функтором?».

✅ Правильный ответ — вариант № 2: объект, реализующий метод map.

Объясняем, почему.

Функтор в JS — это объект, который получает некие значения, преобразует их с помощью внутренней чистой функции и возвращает результат с аналогичной структурой данных. Среди наших вариантов ответа такой метод только один, и это — map.

ℹ Теперь давайте рассмотрим другие варианты.

Sort — изменяет входной массив, т.е. он не является чистой функцией.

Reduce — также может вернуть аналогичную структуру, но это не гарантированно, т.к. он более универсален.

Next — метод для передачи данных следующей итерации, и он не используется для преобразования.

Если остались еще вопросы, задавайте.

@chulakov_dev
  • 👍 17
  • 🔥 4
  • ❤ 1
  • 🤔 1
Post #296 574
  • 👍 13
  • 👏 5
  • ❤ 2
Post #295 559
Привет, друзья!

На прошлой неделе многие из вас справились с задачей по Event Loop 💪🏼 Сможете ли вы правильно ответить на сегодняшний вопрос?

Он ниже вместе с вариантами ответа👇🏻 Выбирайте.
  • 👍 10
  • ❤ 2
  • 🤔 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →