True Frontender
1K subscribers
145 photos
7 videos
89 links
Сборная солянка про фронтенд.

JavaScript, React, TypeScript, HTML, CSS — здесь обсуждаем всё, что связано с веб-разработкой!

Связь: @pmowq
Download Telegram
Привет! Сегодня разберём интересный момент в React с вызовом нескольких setState в одном обработчике.


function App() {
const [count, setCount] = useState(0);

useEffect(() => {
console.log("Effect:", count);
}, [count]);

const handleClick = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};

return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>+3</button>
</div>
);
}


Вопрос
Что выведет консоль, и сколько раз сработает useEffect?

Разбор
1. Все три вызова setCount используют одно и то же значение count, так как React не обновляет состояние мгновенно.
2. React батчит вызовы setState в одном событии. В итоге React применяет только последний вызов, и count становится 1.
3. useEffect срабатывает один раз, так как состояние изменилось только один раз.

Вывод в консоль: Effect: 1


Чтобы каждый вызов setCount учитывал предыдущее состояние, используйте функциональное обновление:

function App() {
const [count, setCount] = useState(0);

useEffect(() => {
console.log("Effect:", count);
}, [count]);

const handleClick = () => {
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
};

return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>+3</button>
</div>
);
}


Теперь каждый вызов setCount получает актуальное значение prev, и count увеличивается правильно, но useEffect всё равно сработает один раз, так как React батчит изменения.

#react
🔥8👍5
Сегодня разберём CSS-свойство — display: contents. Оно редко встречается, но может сильно упростить вёрстку в некоторых кейсах.

Что такое display: contents?
Это свойство заставляет элемент "исчезнуть" из рендера, но его дочерние элементы остаются и ведут себя так, будто родителя нет.

Пример
У нас есть сетка, но лишняя обёртка ломает структуру:

<style>
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}

.inner {
display: contents;
}

p {
background: lightblue;
padding: 10px;
}
</style>

<div class="wrapper">
<div class="inner">
<p>Привет</p>
<p>Мир</p>
</div>
</div>


Без display: contents блок .inner создаёт лишний уровень в сетке, и не попадают в ячейки .wrapper. С display: contents элемент .inner исчезает из рендера, и <p/> становятся прямыми детьми .wrapper для сетки, занимая ячейки.

Когда полезно?
- Убираем лишние обёртки, не ломая семантику HTML.
- Упрощаем работу с Grid и Flexbox, чтобы дети родителя участвовали в сетке напрямую.
- Используем для улучшения доступности.

Поддержка браузерами: Can I Use

#CSS #HTML
8👍5🔥3
Вы пользовались ИИ-редакторами? 🤯

Я недавно попробовал вайбкодить домашние проекты и это просто какой-то шок. Раньше на MVP уходило несколько дней, а сейчас буквально 1–2 часа на фронт и бэк. Главное написать качественный промт, с которым тоже помогает ИИ 😱

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

Как бы грустно это ни звучало, но зима близко 🥶 Конечно, сложно будет заменить программистов из-за качества сгенереного кода, поддержки и в целом понимания продукта, но со временем определённо станет сложнее искать работу(пока выдыхаем) 😕

#career #frontend
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔7👍3👏2🔥1
Заканчиваем серии постов про SOLID! Сегодня разберём последнюю букву - D, которая расшифровывается как Dependency Inversion Principle (Принцип инверсии зависимостей).

О чём этот принцип?
Высокоуровневые модули не должны зависеть от низкоуровневых. Оба должны зависеть от абстракций. А абстракции не должны зависеть от деталей — детали зависят от абстракций.

Если проще - зависите от интерфейсов, а не от конкретных классов. Это делает код гибким и независимым от деталей реализации.

Пример плохого подхода:

class Database {
save(data: string): void {
console.log(`Сохранено в базе: ${data}`);
}
}

class UserService {
private db = new Database();

saveUser(user: string): void {
this.db.save(user);
}
}

const service = new UserService();
service.saveUser("Alice"); // Сохранено в базе: Alice


UserService жёстко привязан к Database. Хотите сохранить данные в файл или API? Придётся переписывать UserService.

Как улучшить?
Введём интерфейс и передадим зависимость через конструктор:

interface Storage {
save(data: string): void;
}

class Database implements Storage {
save(data: string): void {
console.log(`Сохранено в базе: ${data}`);
}
}

class FileStorage implements Storage {
save(data: string): void {
console.log(`Сохранено в файл: ${data}`);
}
}

class UserService {
constructor(private storage: Storage) {}

saveUser(user: string): void {
this.storage.save(user);
}
}

const dbService = new UserService(new Database());
dbService.saveUser("Alice"); // Сохранено в базе: Alice

const fileService = new UserService(new FileStorage());
fileService.saveUser("Bob"); // Сохранено в файл: Bob

Теперь UserService зависит от абстракции Storage.

Что это даёт?
- Легко менять реализацию (база, файл, API) без правок в сервисе.
- Подставляйте моки для тестов.
- Зависимости явные, меньше связей.


#BestPractices #JavaScript #typescript
🔥10👍6
Привет! Недавно мы разбирали нативный метод Object.groupBy, а сегодня разберём задачу с реализацией кастомного groupBy.

Задача
Дан массив объектов:

const users = [
{ name: 'Алиса', age: 21 },
{ name: 'Макс', age: 25 },
{ name: 'Ваня', age: 21 },
];


Нужно сгруппировать по возрасту:

groupBy(users, user => user.age);
// Результат:
// {
// 21: [{ name: 'Алиса', age: 21 }, { name: 'Ваня', age: 21 }],
// 25: [{ name: 'Макс', age: 25 }]
// }


Решение через reduce:

function groupBy(array, fn) {
return array.reduce((acc, item) => {
const key = fn(item);
(acc[key] ||= []).push(item);
return acc;
}, {});
}


Как работает?
1. reduce накапливает объект acc.
2. Для каждого item вычисляем ключ через fn(item).
3. Если ключа нет в acc, создаём массив.
4. Добавляем item в этот массив.
5. Возвращаем обновлённый acc.

#JavaScript #interview
🔥9👍4
Привет! Сегодня разберём StrictMode для разработки в React 🖼️ Он помогает находить потенциальные ошибки и улучшать качество кода.

Что делает StrictMode?
StrictMode активирует дополнительные проверки в режиме разработки:
- Дважды вызывает функции (например, useEffect, useState, конструкторы классов), чтобы выявить побочные эффекты.
- Подскажет, если вы используете методы, которые скоро удалят.
- Находит потенциальные баги, такие как мутации состояния или неправильная работа с хуками.

Как подключить?
Оберните приложение:

ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
);


Советы
- Двойной рендер может раздражать, но он спасает от багов.
- Убедитесь, что useEffect и другие хуки идемпотентны (не ломаются при повторных вызовах).
- Если добавляете StrictMode в легаси проект, будьте готовы к сюрпризам.
- Не отключайте StrictMode без веской причины.

#react #BestPractices
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍3
Привет 👋
Разберём полезный и редко используемый атрибут inputmode. Он говорит браузеру, какую клавиатуру показывать на мобильных устройствах при вводе данных.

Пример:

<input type="text" inputmode="numeric" placeholder="Введите номер телефона" />


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

Доступные значения inputmode
1. text — обычная клавиатура
2. none — клавиатура не показывается
3. tel — клавиатура с цифрами и символами телефона
4. numeric — только цифры
5. decimal — цифры и точка
6. email — клавиатура с @ и .
7. url — клавиатура с / и .
8. search — клавиатура для поиска с кнопкой “Поиск”

Когда использовать
- Для полей, где нужно показать пользователю подходящую клавиатуру для ввода
- Особенно полезно для номеров, кодов, адресов и поиска

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

#HTML #BestPractices
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍71
Привет! 👋
Хочу поделиться историей, которая началась этим летом в июле и до сих пор продолжается.

В одном из дворов мы заметили кота, который выглядел настолько плохо, что пройти мимо было просто невозможно. Худой, в ранах, с кучей проблем, о которых тогда мы ещё даже не подозревали.
Мы решили поймать его и отвезти в больницу, но это оказалось не так просто. Нам не удалось поймать его самим и пришлось искать человека, который умеет ловить животных. К счастью, нам удалось поймать его и отправить в больницу 🏥

Дальше началась самая долгая и тяжёлая часть. Кот провёл много времени в больнице, а каждый день был похож на эмоциональные качели. Постоянно всплывали новые проблемы, долгое время не было никаких улучшений, и оставалось только ждать и надеяться. Я закидывал все анализы и слова врачей в ChatGPT чтобы получить еще одно мнение по состоянию. У кота было столько серьёзных заболеваний, что сложно представить, как он жил с ними. Врачи сделали невозможное 🤯

Сейчас кот здоров настолько, насколько это вообще возможно для его возраста и того, что ему пришлось пережить. Он хорошо ест, набрал вес, живёт спокойной и размеренной жизнью. Он всё ещё боится, когда пытаешься его погладить, но его сердечко очень быстро тает ❤️ У него остались некоторые особенности по здоровью, но это не мешает ему жить и не влияет на качество жизни. Просто котик со своими особенностями)

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

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

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

Любите котиков ❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
27🔥6👏4
Уязвимость в React ⚠️

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

Что случилось?
Ошибка в механизме обработки данных в RSC даёт возможность злоумышленнику отправить специально сформированный запрос и выполнить произвольный код на сервере без авторизации.

Уязвимость получила идентификатор CVE-2025-5518 и максимальный рейтинг критичности.

Кто в зоне риска?
Затронуты проекты, использующие пакеты react-server-dom-* версий 19.0-19.2.0, в том числе через такие фреймворки, как Next.js, React Router RSC, Vite RSC плагины и другие решения с поддержкой Server Components.

Что делать? ⚠️
React уже выпустил исправления. Достаточно обновить зависимости до 19.0.1, 19.1.2 или 19.2.1. И убедитесь, что используемые фреймворки тоже подтянули фикс.

#react #security
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3
С Новым 2026 годом 🎄

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

Спасибо, что читаете канал и не отписываетесь)

С Новым годом 🍾
Please open Telegram to view this post
VIEW IN TELEGRAM
🎄1410
Проводя собеседования, я заметил, что часть разработчиков не знают базу. И речь не про новичков, это люди с опытом в несколько лет 😱

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

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

Я рекомендую не накручивать опыт, если у вас нет хорошей базы, так как таких кандидатов не будут рассматривать на грейд ниже. А возможно даже сделают пометку, и в следующий раз не дадут возможность повторно пройти собеседование.
Также не стоит расписывать достижения, если вы не можете их объяснить, и не стоит указывать(спросят только так) конкретные цифры, за которыми не стоит реального понимания.

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

Собеседование - это улица из 2010 🙄
Здесь могут докопаться до любого вашего слова, до каждой детали в резюме. Не стоит говорить и писать лишнего, так будет меньше вопросов 🥴 А если уж что-то пишете или говорите, будьте готовы отвечать 🤜

#JavaScript #interview #career
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥4