truefrontender | Unsorted

Telegram-канал truefrontender - True Frontender

1070

Сборная солянка про фронтенд. JavaScript, React, TypeScript, HTML, CSS — здесь обсуждаем всё, что связано с веб-разработкой! Связь: @pmowq

Subscribe to a channel

True Frontender

Одна из распространённых ошибок при работе с React — вызов хуков внутри условий, циклов или вложенных функций 🖼️

Пример кода с ошибкой:


function Component({ show }) {
if (show) {
useEffect(() => {
console.log("Какой-то эффект");
}, []);
}

return <div>Тут что-то интересное!</div>;
}


Ошибка: Invalid hook call

Исправление ошибки:

function Component({ show }) {
useEffect(() => {
if (show) {
console.log("Какой-то эффект");
}
}, [show]);

return <div>Тут что-то интересное!</div>;
}


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

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

#react

Читать полностью…

True Frontender

Привет! Готовы к короткой рабочей неделе? Давайте начнем ее с формошлепства.

Иногда дизайнеры рисуют сложные формы — поля в одном месте, кнопки в другом. Cамый простой вариант, который приходит в голову — обернуть всё в форму. Да, это работает, но в большинстве случаев это приведёт как минимум к багам, а максимум — к архитектурным проблемам.

Что делать?
Связать кнопку с формой через атрибут form.
Этот атрибут позволяет кнопке отправлять форму, даже если она расположена вне её, благодаря привязке через id.


<form id="contactForm">
<input type="text" name="name" />
</form>

<!-- Кнопка вне формы -->
<button type="submit" form="contactForm">Сохранить</button>


Как это работает?
1. <form> получает id.
2. Кнопка вне формы указывает на этот id через атрибут form.
3. Браузер связывает кнопку с формой и корректно обрабатывает submit.

#HTML #BestPractices

Читать полностью…

True Frontender

Разберём ещё один полезный утилити-тип — Awaited 🖼️. Он позволяет извлечь тип результата из промиса.

Что делает Awaited?
Awaited<T> возвращает тип, в который разрешается промис T.
Проще говоря — убирает Promise-обёртку и достаёт внутренний тип.

Пример:


async function fetchData(): Promise<string> {
return "Строка с данными";
}

type ResultType = Awaited<ReturnType<typeof fetchData>>;
// Тип: string


Здесь мы комбинируем два утилити-типа — ReturnType (о котором я писал в этом посте) и Awaited.

Сначала ReturnType<typeof fetchData> даёт нам Promise<string>, а затем Awaited вытаскивает из него string.

#typescript

Читать полностью…

True Frontender

Почти каждый из нас работает с TypeScript, и большинство сталкивалось с пересечением типов.

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


interface Employee {
name: string;
position: string
}

interface ContactInfo {
email: string;
phone: string
}

type EmployeeContact = Employee & ContactInfo;

const employee: EmployeeContact = {
name: 'Иван',
position: 'Разработчик',
email: 'ivan@google.com',
phone: '+7(900)-000-0000'
};


Тип EmployeeContact включает в себя как поля из типа Employee, так и поля из типа ContactInfo.

Важно
Когда два типа имеют одинаковые поля с различными типами, это приводит к ошибке. В TypeScript такие поля получают тип never, что делает невозможным присваивание значений.

#typescript

Читать полностью…

True Frontender

Подборка пятничных мемов 😋

Читать полностью…

True Frontender

Сегодня база про cookie. Мы работаем с ними каждый день, и про них спрашивают почти на каждом собеседовании.

Что такое cookie?
Cookie — это строка с данными, которую браузер сохраняет и автоматически отправляет серверу при каждом HTTP-запросе.

Как устанавливаются куки?


document.cookie = "token=abc123; path=/; max-age=3600";


Как еще можно установить?
Куки могут быть установлены сервером через HTTP-ответы с помощью заголовка Set-Cookie. Когда сервер хочет установить куку на клиенте, он отправляет этот заголовок в ответе на запрос.

Свойства:
1. path: Определяет путь, для которого кука будет доступна. По умолчанию: / — доступна на всем сайте.

2. expires: Устанавливает дату истечения срока действия куки. По умолчанию: кука сессионная и удаляется при закрытии браузера.

3. max-age: Устанавливает время жизни куки в секундах. По умолчанию: не указан, кука сессионная.

4. secure: Указывает, что кука будет передаваться только по HTTPS. По умолчанию: не установлен, кука будет передаваться как по HTTP, так и по HTTPS.

5. samesite: Определяет, можно ли отправлять куку с запросами на другие сайты. По умолчанию: не указан, кука отправляется с запросами как с того же сайта, так и с внешних источников.

6. httpOnly: Указывает, что кука будет доступна только для сервера и не может быть прочитана через JavaScript. Это улучшает безопасность, предотвращая атаки. По умолчанию: не установлен.

Удаление cookies:
Можно удалить куку, установив её с датой, которая уже прошла, или задать значение max-age равным 0 или отрицательным числом.

Особенности:
1. Максимальный размер не должен превышать 4 KB.
2. Куки отправляются на каждый запрос.

#JavaScript

Читать полностью…

True Frontender

Подборка пятничных мемов 🌈

Читать полностью…

True Frontender

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

Что за хук?
useDeferredValue — это хук из React 18, который позволяет "откладывать" обновление части интерфейса. Он принимает значение и возвращает его "отложенную" версию. Это значение обновляется только после того, как React завершит рендеринг более приоритетных задач.

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


import { useState, useDeferredValue } from "react";

function App() {
const [query, setQuery] = useState("");
const deferredQuery = useDeferredValue(query);

return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Введите текст"
/>
<List query={deferredQuery} />
</div>
);
}

function List({ query }) {
const items = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);
const filteredItems = items.filter((item) =>
item.toLowerCase().includes(query.toLowerCase())
);

return (
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}


Как это работает?
1. Пользователь вводит текст в инпут.
2. Состояние query обновляется сразу, но deferredQuery обновляется с задержкой.
3. Компонент List использует deferredQuery, чтобы отфильтровать элементы. Благодаря этому:
— Инпут не зависает.
— Фильтрация списка происходит чуть позже, когда React "освободится".

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

#react #BestPractices

Читать полностью…

True Frontender

Начинаем с поста о малоизвестном свойстве у input — valueAsNumber. Оно позволяет работать с числами напрямую, без ручного преобразования типов.

Что это за свойство?
Когда вы используете <input type="number">, значение по умолчанию возвращается как строка:


const value = input.value;
console.log(typeof value); // "string"

Чтобы получить число, чаще всего используют Number(value) или parseFloat(value).

Но есть более нативный способ — valueAsNumber:

const numberValue = input.valueAsNumber;
console.log(typeof numberValue); // "number"



Что будет при некорректном вводе?
Если поле пустое или в нём невалидное значение, valueAsNumber вернёт NaN. Это нужно учитывать при работе с данными:

if (!Number.isNaN(numberValue)) {
// значение можно использовать
} else {
// обработка ошибки
}

Про работу с числами я писал в этом(тык) посте.

Когда стоит использовать:
- При работе с числовыми значениями из форм
- Чтобы избежать лишнего преобразования типов
- Для более чистого кода

#JavaScript

Читать полностью…

True Frontender

Сегодня поговорим о еще одном полезном утилити-типе в TypeScript — Record<Keys, Type>. Этот тип позволяет создавать объекты с определенными ключами и значениями

Что такое Record?
Record<Keys, Type> — это утилита, которая создает объектный тип, где:
- Keys — набор ключей (обычно строковые литералы или объединение строк).
- Type — тип значений, которые будут связаны с этими ключами.

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

Пример использования
Предположим, у нас есть список цветов, и мы хотим связать каждый цвет с его HEX-кодом:


type Colors = 'red' | 'green' | 'blue';

type ColorHex = Record<Colors, string>;

const colorCodes: ColorHex = {
red: '#FF0000',
green: '#00FF00',
blue: '#0000FF',
};


Что происходит:
- Мы определили тип Colors, который является объединением строковых литералов ('red', 'green', 'blue').
- Использовали Record, чтобы создать объект, где каждому ключу из Colors соответствует строковое значение (HEX-код).

Теперь TypeScript гарантирует, что:
- Все ключи из Colors присутствуют в объекте.
- Значения имеют тип string.

Используйте Record, когда вам нужно описать объект с заранее известными ключами и типами значений.

#typescript

Читать полностью…

True Frontender

⚡️React становится платным!⚡️

Meta официально объявила, что с 1 апреля 2025 года React переходит на подписку!
Теперь за использование библиотеки придётся платить $9.99/мес для разработчиков и $199/мес для компаний.

Основные изменения:
1️⃣ Бесплатной останется только React 17, но без обновлений.
2️⃣ В React 18+ появится DRM-защита – проект не соберется без лицензионного ключа.
3️⃣ В консоли будет всплывать огромный красный баннер: ⚠️ "React is unlicensed. Please purchase a subscription."
4️⃣ Удалены оптимизации (useMemo, useCallback, React.memo).

Кряк платной версии
На GitHub слили react18-crack.js, который:
Возвращает вырезанный функционал для оптимизации.
Подставляет лицензионный ключ REACT_ENTERPRISE_EDITION=TRUE
Отключает баннер "React is unlicensed" в консоли.

Что делать без кряка?
1️⃣Платить за подписку.
2️⃣ Пересаживаться на Vue.
3️⃣Переписывать всё на jQuery.

#react

Читать полностью…

True Frontender

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

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

Подписывайтесь @TrueFrontenderChat ☺️

А я ухожу на выходные отдыхать и готовить для вас новые посты)
Всем хороших выходных, встретимся в понедельник!

P.S. Не забывайте ставить реакции. Вам не сложно, мне приятно 🥰

Читать полностью…

True Frontender

Знали ли вы о свойстве text-decoration-skip-ink?
Это свойство, которое управляет поведением, когда линия проходит через часть символа или глифа. Это даёт контроль над тем, как подчеркивания взаимодействуют с символами.

Как это работает?
По умолчанию браузеры пропускают области, где символы пересекают линию подчеркивания, что делает текст более читаемым и эстетичным.

Есть 2(3) значения:
1. Когда установлено auto, браузер сам решает, где пропустить линию подчеркивания, чтобы улучшить читаемость текста. Например, подчеркивание будет пропущено через те части символов, которые нарушают его целостность.


a {
text-decoration: underline;
text-decoration-skip-ink: auto; /* Браузер сам решает, где пропустить линию */
}


2. Если значение установлено на none, то линия подчеркивания будет проходить через все символы, независимо от того, пересекает ли она их соединительные элементы. Это может быть полезно, если вы хотите, чтобы подчеркивание было единообразным и охватывало весь текст.


a {
text-decoration: underline;
text-decoration-skip-ink: none; /* Линия будет проходить через все символы */
}


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

#CSS

Читать полностью…

True Frontender

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

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

Одна из популярных задач — написать функцию sum, которая позволяет складывать числа последовательно:


sum(1)(2)(3)(); // 6
sum(5)(-1)(2)(3)(); // 9
sum(10)(20)(30)(40)(50)(); // 150


Решение:

function sum(a) {
return (b) => b === undefined ? a : sum(a + b);
}


Объяснение:
- Первый вызов "sum(1)" возвращает функцию с замыканием, где a = 1.
- Второй вызов "(2)" накапливает сумму: 1 + 2 = 3.
- Третий вызов "(3)" увеличивает сумму: 3 + 3 = 6.
- Финальный вызов "()" условие b === undefined становится истинным, и возвращается результат — 6.

Кратко:
Функция sum использует рекурсию и замыкание, чтобы накапливать сумму и возвращать результат при вызове без аргументов.

Небольшое уточнение:
Это не классическая рекурсия, а комбинация замыканий и каррирования. Функция накапливает сумму через замыкания и завершает вычисление при вызове без аргумента.

#interview #JavaScript

Читать полностью…

True Frontender

Предлагаю сегодня снова немного расслабиться перед выходными 🤗

А вы часто копируете чужой код? Или, может быть, пользуетесь ИИ?

Читать полностью…

True Frontender

Видели сайты с красивым скроллом фона? Это легко сделать самому, используя всего одно свойство CSS — background-attachment: fixed;.

Демо и код тут: CodePen

Поддержка браузерами: CanIUse

#css

Читать полностью…

True Frontender

Пятничная подборка мемов 😂

Не забывайте, что у нас есть чат. Всем хороших выходных!

Читать полностью…

True Frontender

Сделал небольшую шпаргалку со всеми типами инпутов

Ссылка на шпаргалку: CodePen

Читать полностью…

True Frontender

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

Что выведет этот код?


var a = 5;

function f() {
if (a) {
console.log(a);
var a = 10;
}
}

f();



Ответ:
Ничего не будет выведено.

Разбор:
1. Переменная a внутри функции f поднимается в начало функции, но её значение остаётся undefined до строки var a = 10;.
2. В условии проверяется undefined, поэтому console.log(a) не вызывается.

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

#JavaScript #interview

Читать полностью…

True Frontender

Один из моих любимых утилити-типов в TypeScript — ReturnType. Сегодня пост о нём.

Что делает ReturnType?
ReturnType<T> — извлекает тип возвращаемого значения из функции T.

Пример:


function getUser() {
return { id: 1, name: 'Василий' };
}

type User = ReturnType<typeof getUser>;
// { id: number, name: string }


Теперь User всегда будет соответствовать тому, что возвращает getUser.

Где применять?
У меня есть идеальный кейс на одном из проектов: компонент, который завязан на данные из хука. Тут идеально подходит ReturnType — можно получить тип возвращаемого значения хука и использовать его в пропсах компонента.

Что-то на подобии такого:

// Какой-то хук с логикой
function useUserData() {}

// Пропсы компонента
interface Props {
data: ReturnType<typeof useUserData>;
};

function UserInfo({ data }: Props) {}


Конечно, мы можем создать отдельный тип и использовать его и в хукe, и в компоненте, но тогда при изменениях придётся править в нескольких местах.

interface User {}

function useUserData(): User {}

interface Props {
data: User;
};

function UserInfo({ data }: Props) {}


Это не единственное применение ReturnType. Главное знать о его существовании и сами найдете применение в своем проекте)

#typescript

Читать полностью…

True Frontender

Привет 👋
Задача, снова задача) Через тренировки можно подготовиться к большинству собеседований.

Условие:
Нужно дописать функцию, которая принимает два параметра:
1. Массив чисел
2. Функцию-предикат, которая принимает значение элемента массива и возвращает true или false.

Нужно найти в массиве индекс элемента, для которого предикат вернет true. Если такого элемента нет, вернуть -1.

Входные параметры:


findInArray([1, 3, 5, 6, 7], (value) => value % 2 === 0); // Должно вернуть 3
findInArray([1, 3, 5, 7], (value) => value % 2 === 0); // Должно вернуть -1


Решение:

const findInArray = (arr, predicate) => arr.findIndex(predicate);


И все? Да, и все 😅 Многие могут начать писать функции, в которых используют цикл for, но в JS уже есть встроенные методы о которых нужно знать и использовать.

#interview #JavaScript

Читать полностью…

True Frontender

Инструмент недели — CSS Loaders

Мы часто сталкиваемся с проблемой отображения состояния загрузки. На CSS Loaders собраны готовые анимации лоадеров и все они на чистом CSS

Посмотреть можно тут: css-loaders.com

#css

Читать полностью…

True Frontender

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

Что выведет этот код в консоль?


Promise.resolve(123)
.then((x) => x + 1)
.catch((x) => x + 2)
.then((x) => x + 3)
.then((x) => console.log(x));


Ответ: 127

Объяснение:
1. Promise.resolve(123) — промис сразу выполняется со значением 123.
2. .then((x) => x + 1) — прибавляем 1 к 123.
3. .catch((x) => x + 2) — пропускается, так как ошибки не было.
4. .then((x) => x + 3) — прибавляем 3 к 124.
5. .then(console.log) — выводим в консоль 127.

Важно:
catch срабатывает только при необработанной ошибке. В нашем случае ошибок нет, значит пропускаем.

#interview #JavaScript

Читать полностью…

True Frontender

Хочу попросить ваш фидбек — кажется, активность немного снизилась. Чего-то не хватает или может не заходит формат?

Поделитесь мыслями, я обязательно учту все комментарии (как минимум, запишу в свой блокнот) 🤔

Читать полностью…

True Frontender

Закончили с шутками и возвращаемся к привычным постам 🤗

Знали ли вы, что в CSS можно задавать переменные с конкретным типом через @property?
Теперь переменные могут быть не просто строками, а, например, числами, цветами или процентами. Это позволяет браузеру правильно интерпретировать их и использовать без ошибок.

Как объявить типизированную переменную?
Допустим, мы хотим создать переменную для управления размером элемента.

Раньше:


:root {
--size: 50;
}


Сейчас можно явно указать, что --size — это число:

@property --size {
syntax: "<number>";
inherits: false;
initial-value: 10;
}


Теперь --size можно безопасно использовать в calc, transform и других свойствах.

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

@property --scale {
syntax: "<number>";
inherits: false;
initial-value: 1;
}

.box {
--scale: 1;
transform: scale(var(--scale));
transition: --scale 0.5s ease;
}

.box:hover {
--scale: 1.2;
}


Что если задать неверное значение?
Если задать неверное значение, браузер просто проигнорирует его и оставит предыдущее корректное или начальное значение из @property.

Поддержка браузерами: CanIUse

#css

Читать полностью…

True Frontender

Привет! Начнем неделю с задачи про контекст. Очень распростроенная задача

Что будет выведено в консоль?


for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}


Ответ:
5, 5, 5, 5, 5

Почему так происходит?
- Колбеки setTimeout выполняются после завершения цикла.
- Переменная i общая для всех итераций, и к моменту выполнения становится равной 5.
- Все колбеки ссылаются на одну переменную i, которая уже имеет конечное значение.

Как исправить?
1. Использование let вместо var
Переменные, объявленные через let, имеют блочную область видимости. Это значит, что каждая итерация цикла будет иметь свою собственную переменную i.


for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}


2. Использование IIFE
Мы можем создать новую область видимости для каждой итерации с помощью IIFE. Анонимная функция вызывается сразу же, передавая текущее значение i как параметр.

for (var i = 0; i < 5; i++) {
(function(currentI) {
setTimeout(function() {
console.log(currentI);
}, 0);
})(i);
}


3. Использование дополнительного параметра в setTimeout
Функция setTimeout может принимать дополнительные аргументы, которые будут переданы в callback.

for (var i = 0; i < 5; i++) {
setTimeout(function(currentI) {
console.log(currentI);
}, 0, i);
}


4. Использование bind
Можно использовать метод bind для привязки значения i к callback-функции.


for (var i = 0; i < 5; i++) {
setTimeout(console.log.bind(null, i), 0);
}


Во всех этих вариантах результат будет: 0, 1, 2, 3, 4.


Вроде простая задача, но она проверяет, как собеседующийся понимает работу event loop, областей видимости и замыканий.

#JavaScript #interview

Читать полностью…

True Frontender

Сегодня отдыхаем 🍻
Наверное, не только у меня была тяжелая неделя, и хочется чуть-чуть потупить. Уже входит в привычку тупить по пятницам 😬

Делюсь демкой, на которую как-то наткнулся. Анимация переключения показалась мне достаточно интересной.
А ещё напоминаю, что вы можете поделиться своими находками в комментариях. Возможно, кто-то сам делает что-то подобное)

Ссылка на демо: CodePen

#CSS #animation

Читать полностью…

True Frontender

Продолжаем разбирать утилити-типы TypeScript. Сегодня на очереди Readonly<T>.

Этот тип делает все свойства объекта неизменяемыми. После создания объекта с Readonly, его свойства нельзя изменить, что помогает защитить данные от случайных изменений.

Зачем нужен Readonly?
1. Защита данных — предотвращает изменения объекта, если этого не должно происходить.
2. Предсказуемость кода — помогает избежать неожиданных багов, когда данные случайно изменяются.
3. Работа с неизменяемыми структурами данных — полезно для Redux, конфигурационных объектов и API-ответов.

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


interface User {
name: string;
age: number;
};

type ReadonlyUser = Readonly<User>;


Что в итоге получится:

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


Теперь при попытке изменить свойства такого объекта TypeScript выдаст ошибку:

const user: ReadonlyUser = { name: "Alice", age: 25 };
user.age = 26; // Cannot assign to age because it is a read-only property.


Использовать Readonly стоит в ситуациях, когда объект не должен модифицироваться после создания: для конфигурационных данных, API-ответов, неизменяемых структур и управления состоянием в приложении.

#typescript #interview

Читать полностью…

True Frontender

Привет! Давайте начнем эту неделю с необычной для понедельника темы — поговорим о валидации форм в React.

Валидация данных — важная часть разработки. Можно проверять данные вручную, но это неудобно и приводит к громоздкому коду. Zod позволяет описывать структуры данных декларативно и сразу проверять их корректность.

Пример


import { z } from "zod";

const userSchema = z.object({
name: z.string(),
age: z.number().min(18),
});

const result = userSchema.safeParse({ name: "Антон", age: 42 });

if (!result.success) {
console.log(result.error.format()); // Ошибка: возраст должен быть 18+
}


Zod + TypeScript

type User = z.infer<typeof userSchema>;


User — это автоматически сгенерированный тип, который всегда соответствует схеме.

Простая валидация формы
Используем Zod вместе с React Hook Form, чтобы валидировать форму без лишнего кода.

import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";

const formSchema = z.object({
email: z.string().email(),
password: z.string().min(6, "Пароль должен содержать минимум 6 символов"),
});

type FormData = z.infer<typeof formSchema>;

export function LoginForm() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormData>({
resolver: zodResolver(formSchema),
});

const onSubmit = (data: FormData) => {
console.log("Успешный ввод:", data);
};

return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Email:</label>
<input {...register("email")} />
{errors.email && <p>{errors.email.message}</p>}
</div>

<div>
<label>Пароль:</label>
<input type="password" {...register("password")} />
{errors.password && <p>{errors.password.message}</p>}
</div>

<button type="submit">Войти</button>
</form>
);
}


Почему Zod?
- Чистый синтаксис – описание схем читается легко
- Работает с TypeScript – выводит типы автоматически
- Без внешних зависимостей
- Можно использовать в API, формах, конфигурациях

Итог
Zod — это отличный инструмент, который упрощает валидацию данных. Он избавляет от громоздких проверок вручную, отлично интегрируется с TypeScript и React Hook Form и тд

#react #OpenSource #typescript

Читать полностью…

True Frontender

Инструмент недели — CSS Animation Generator.

Этот сайт позволяет легко и наглядно создавать анимации с помощью удобного интерфейса.

Настраиваете ключевые кадры, длительность, задержку и тип анимации, а генератор сразу выдаёт готовый CSS или JS код.

Попробовать можно тут: angrytools

#css

Читать полностью…
Subscribe to a channel