С появлением React Hooks в версии 16.8 (2019 год) классовые компоненты стали устаревшим способом создания компонентов. Сегодня функциональные компоненты с хуками заменяют классы. Давайте разберем почему.
Функциональные компоненты короче, читаются легче, а код становится чище.
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<button onClick={this.increment}>
Счетчик: {this.state.count}
</button>
);
}
}
Функциональный компонент (хуки делают код проще)
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Счетчик: {count}
</button>
);
}
В классах жизненный цикл* компонента состоит из нескольких методов (
componentDidMount
, componentDidUpdate
, componentWillUnmount
). class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { time: 0 };
}
componentDidMount() {
this.timer = setInterval(() => {
this.setState({ time: this.state.time + 1 });
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
render() {
return <p>Время: {this.state.time} секунд</p>;
}
}
Функциональный компонент (хуки делают все проще)
function Timer() {
const [time, setTime] = useState(0);
useEffect(() => {
const timer = setInterval(() => setTime(t => t + 1), 1000);
return () => clearInterval(timer);
}, []);
return <p>Время: {time} секунд</p>;
}
Классовые компоненты используют экземпляры классов, а функциональные компоненты – просто функции.
Создают экземпляры
this
Обрабатывают
setState
Хранят лишние связи и контексты
Не создают
this
Используют только нужные данные
Оптимизируются через React.memo
const Button = React.memo(({ onClick }) => {
console.log("Ререндер кнопки");
return <button onClick={onClick}>Нажми</button>;
});
function App() {
const [count, setCount] = useState(0);
const increment = useCallback(() => setCount(c => c + 1), []);
return (
<div>
<p>Счетчик: {count}</p>
<Button onClick={increment} />
</div>
);
}
Раньше в классах код переиспользовали через HOC и Render Props, но это делало код сложным.
function withLogging(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log("Компонент монтирован");
}
render() {
return <WrappedComponent {...this.props} />;
}
};
}
Хуки (
useEffect
) делают код чище function useLogger() {
useEffect(() => console.log("Компонент монтирован"), []);
}
function MyComponent() {
useLogger();
return <p>Привет, мир!</p>;
}
React официально рекомендует использовать функциональные компоненты
Dan Abramov (разработчик React)
Новые фичи React (Suspense, Server Components) создаются для функциональных компонентов
Классы не работают в React Server Components
Большинство современных библиотек (Redux Toolkit, React Query) рассчитаны на хуки
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4😁2
- <header> для заголовков.
- <article> для статей.
- Семантический HTML улучшает SEO, доступность и структуру кода.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥3
innerHTML
– это свойство, которое позволяет вставлять HTML-код внутрь элемента как строку. Однако оно небезопасно и может привести к серьезным проблемам. document.getElementById("content").innerHTML = "<h1>Привет!</h1>";
Если
innerHTML
получает данные от пользователя (например, из формы или URL), хакер может вставить вредоносный JavaScript-код. const userInput = "<script>alert('Вас взломали!');</script>";
document.getElementById("content").innerHTML = userInput;
Если в веб-приложении включена CSP (защита от XSS), то
innerHTML
может нарушать политику безопасности. <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
Если заменить содержимое элемента через
innerHTML
, все обработчики событий внутри него удалятся. document.getElementById("btn").addEventListener("click", () => {
alert("Нажато!");
});
document.getElementById("container").innerHTML = "<button id='btn'>Клик</button>";
document.getElementById("btn").click(); // Ошибка, обработчик удален
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12😁1
1. Компонентный подход: Упрощает создание и повторное использование UI-элементов.
2. Виртуальный DOM: Повышает производительность благодаря минимизации операций с реальным DOM.
3. Большая экосистема: Множество библиотек и инструментов для разработки.
4. Универсальность: Подходит как для веб-приложений, так и для мобильных (React Native).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22💊6😁5🔥3❤2
В веб-разработке часто возникает вопрос: использовать кнопку (
<button>
) или ссылку (<a>
) для взаимодействий? Хотя они внешне могут выглядеть одинаково, у них разные назначения и поведение. Когда действие выполняется на странице без перехода на другую
Когда нужна интерактивность (отправка формы, открытие модального окна, запуск скрипта)
Отправка формы
Открытие/закрытие модального окна
Включение/выключение чего-то на странице
Взаимодействие с JavaScript (AJAX-запросы, события)
<button onclick="alert('Нажато!')">Кликни</button>
Пример кнопки в форме:
<form>
<input type="text" placeholder="Введите имя">
<button type="submit">Отправить</button>
</form>
Когда нужно перейти на другую страницу (или секцию сайта)
Когда ссылка ведет на внешний или внутренний ресурс
Навигация по сайту
Переход на другую страницу
Ссылки на соцсети, статьи, файлы
<a href="https://example.com">Перейти на сайт</a>
Ссылка внутри страницы (якорь)
<a href="#section">Перейти вниз</a>
<section id="section">Контент</section>
Открытие в новом окне
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
Открыть в новой вкладке
</a>
Ошибка: использовать
<button>
вместо ссылки<button onclick="window.location.href='https://example.com'">Перейти</button>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍12💊1
1. Единое хранилище: Все состояние приложения хранится в одном объекте.
2. Принцип "однонаправленного потока данных": Состояние изменяется через действия (actions) и редюсеры (reducers).
3. Удобство тестирования: Легко отслеживать изменения состояния.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥2
Flexbox (Flexible Box Layout) – это модель размещения элементов в CSS, которая делает макет гибким и удобным для адаптивной верстки.
Главные особенности
элементов в строку или колонку
пространства между элементами
без
float
и position
элементов
Когда включается
display: flex;
, элементы внутри него становятся флекс-элементами. Flex-контейнер → родительский элемент (
display: flex;
) Flex-элементы → дочерние элементы контейнера
Главная ось (main axis) → ось, вдоль которой расположены элементы
Поперечная ось (cross axis) → перпендикулярная ось
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
.container {
display: flex;
}
Включает Flexbox для контейнера.
.container {
display: flex;
}
Определяет, как располагаются элементы (по горизонтали или вертикали).
.container {
flex-direction: row; /* По умолчанию: слева направо */
}
/* Другие значения */
.container {
flex-direction: column; /* В столбик */
flex-direction: row-reverse; /* Справа налево */
flex-direction: column-reverse; /* Вниз-вверх */
}
.container {
justify-content: flex-start; /* По умолчанию, слева направо */
justify-content: center; /* Центр */
justify-content: flex-end; /* Справа налево */
justify-content: space-between; /* Равномерное распределение */
justify-content: space-around; /* С отступами */
justify-content: space-evenly; /* Равномерные промежутки */
}
.container {
align-items: stretch; /* По умолчанию (растягивает) */
align-items: center; /* Центр по вертикали */
align-items: flex-start; /* Вверх */
align-items: flex-end; /* Вниз */
align-items: baseline; /* По базовой линии текста */
}
.container {
flex-wrap: nowrap; /* По умолчанию – все в одной строке */
flex-wrap: wrap; /* Элементы переносятся */
flex-wrap: wrap-reverse; /* Перенос в обратном порядке */
}
Работает, когда элементы занимают несколько строк.
.container {
align-content: flex-start; /* Вверх */
align-content: flex-end; /* Вниз */
align-content: center; /* По центру */
align-content: space-between; /* Равномерное распределение */
align-content: space-around; /* С отступами */
align-content: stretch; /* Растянуть (по умолчанию) */
}
flex-grow
– рост элемента .item {
flex-grow: 1; /* Растянется, если есть место */
}
flex-shrink
– сжатие элемента .item {
flex-shrink: 0; /* Не уменьшаться */
}
flex-basis
– начальный размер элемента.item {
flex-basis: 200px; /* Фиксированный размер */
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26
1. Объединяет файлы: Собирает модули в один файл для улучшения производительности.
2. Обработка ресурсов: Подключает стили, изображения, шрифты.
3. Оптимизация: Минимизирует код, разделяет файлы на части (chunking).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥2💊1
В JavaScript значения, которые при приведении к логическому типу (boolean) становятся
false
, называются "falsy" значениями. Существует всего семь таких значений:Логическое значение
false
. console.log(Boolean(false)); // false
Число ноль.
console.log(Boolean(0)); // false
Отрицательное число ноль (хотя это редко встречается на практике).
console.log(Boolean(-0)); // false
Число
BigInt
с значением ноль. console.log(Boolean(0n)); // false
Строка без символов.
console.log(Boolean("")); // false
Специальное значение, обозначающее отсутствие какого-либо значения.
console.log(Boolean(null)); // false
Специальное значение, обозначающее необъявленное или неприсвоенное значение.
console.log(Boolean(undefined)); // false
Специальное значение, обозначающее не число (Not-a-Number).
console.log(Boolean(NaN)); // false
В условиях (if statements) все falsy значения интерпретируются как
false
.const values = [false, 0, -0, 0n, "", null, undefined, NaN];
values.forEach(value => {
if (!value) {
console.log(`${value} is falsy`);
}
});
Примеры в условиях
if (!false) {
console.log('false is falsy'); // выводится
}
if (!0) {
console.log('0 is falsy'); // выводится
}
if (!"") {
console.log('"" is falsy'); // выводится
}
if (!null) {
console.log('null is falsy'); // выводится
}
if (!undefined) {
console.log('undefined is falsy'); // выводится
}
if (!NaN) {
console.log('NaN is falsy'); // выводится
}
Falsy значения также учитываются в логических операциях.
const value = null;
const result = value || 'default value';
console.log(result); // 'default value', потому что value является falsy
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥2
1. Уязвимость XSS: Если строка содержит вредоносный код, это может быть использовано злоумышленниками.
2. Нарушение безопасности: Непроверенные строки могут модифицировать структуру DOM.
3. Практика: Вместо строки используйте методы, которые безопасно добавляют элементы или текст (innerText, textContent).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊19👍11🔥4
Это инструмент для создания, развертывания и управления контейнерами. Контейнер – это изолированная среда, которая содержит всё необходимое для работы приложения: код, зависимости, библиотеки, конфигурации.
В разных средах могут быть разные версии зависимостей (Node.js, Python, базы данных). С Docker всё упаковано в контейнер, и приложение работает одинаково на любом сервере.
Без Docker развертывание – это настройка сервера, установка зависимостей, конфигурация окружения. С Docker – просто запускаем контейнер.
Docker-контейнеры можно клонировать и запускать на разных серверах (например, в Kubernetes).
Каждое приложение работает в изолированной среде, и конфликты библиотек исключены.
Контейнер можно запустить где угодно, где установлен Docker.
Пример для Node.js-приложения
# Базовый образ с Node.js
FROM node:18
# Устанавливаем рабочую директорию
WORKDIR /app
# Копируем файлы проекта
COPY package.json ./
RUN npm install
COPY . .
# Запускаем приложение
CMD ["node", "server.js"]
Собираем образ Docker (создаем "упакованный" контейнер)
docker build -t my-app .
Запускаем контейнер
docker run -p 3000:3000 my-app
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍35❤2🔥2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥7
bind()
– это метод, который создает новую функцию с привязанным контекстом (this
) и (опционально) фиксированными аргументами. Привязывает
this
, чтобы не потерять контекст Позволяет создавать частично примененные функции
Используется в обработчиках событий и таймерах
Пример: потеря
this
без bind()
const user = {
name: "Иван",
sayHello() {
console.log(`Привет, ${this.name}!`);
},
};
setTimeout(user.sayHello, 1000); // ❌ this = undefined
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤2
Это структура данных, используемая JavaScript-движком для управления выполнением функций. Когда функция вызывается, она добавляется в стек, и выполнение приостанавливается, пока она не завершится. После завершения функции она удаляется из стека, и управление возвращается к предыдущему вызову.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍6
Event Loop (Цикл событий) – это механизм, который управляет выполнением кода, обработкой асинхронных задач и взаимодействием с Web API.
Используем асинхронный код:
setTimeout
, setInterval
, fetch
, Promise
, async/await
Оптимизируем выполнение тяжелых задач
Управляем приоритетами выполнения (Microtask vs Macrotask)
JavaScript выполняет код в однопоточном режиме, но может обрабатывать асинхронные задачи через очередь событий (Event Queue) и микрозадачи (Microtask Queue).
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
Вывод в консоли
1
4
3
2
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29🔥3💊3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊40👍19🤯8😁4
Основная причина – ускорение загрузки страницы и избежание блокировки рендеринга.
Когда браузер загружает HTML, он читает код сверху вниз. Если в
<head>
встречается <script>
, браузер останавливает разбор HTML, загружает и выполняет скрипт, а только потом продолжает загружать страницу. Если скрипт загружается в
<head>
, он останавливает отрисовку страницы до завершения загрузки. <head>
<script src="script.js"></script> <!-- ❌ Плохо: блокирует рендеринг -->
</head>
<body>
<h1>Сайт загружается...</h1>
</body>
Если разместить
<script>
перед закрывающим </body>
, сначала загружается контент страницы, а потом выполняется JavaScript. <body>
<h1>Контент загрузился!</h1>
<script src="script.js"></script> <!-- Хорошо: не блокирует рендеринг -->
</body>
defer
– отложенное выполнение после загрузки HTML<head>
<script src="script.js" defer></script>
</head>
async
– загрузка и выполнение параллельно <head>
<script src="script.js" async></script>
</head>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍33❤5😁1💊1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥7💊1
При разработке frontend-приложений, которые в будущем будет проще поддерживать и масштабировать, я придерживаюсь ряда ключевых подходов.
Это значит, что код должен быть разделен по зонам ответственности. В frontend-разработке это проявляется в:
Чистом разделении логики, представления и данных (например, с помощью архитектуры MVC, MVVM или FLUX).
Использовании компонентов в React/Vue или шаблонов в Angular.
Разделении CSS, JS и HTML, либо использовании методологий, где стили хранятся рядом с компонентом (CSS Modules, Styled Components).
Вместо того, чтобы писать всю логику и разметку в одном файле:
function App() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
Я разделяю бизнес-логику и представление
// CounterLogic.js
export function useCounter() {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return { count, increment };
}
// Counter.js
import { useCounter } from "./CounterLogic";
function Counter() {
const { count, increment } = useCounter();
return <button onClick={increment}>Count: {count}</button>;
}
Frontend-приложения должны строиться из переиспользуемых и изолированных компонентов. Это уменьшает дублирование кода и делает его понятным.
// Button.js (переиспользуемый компонент)
function Button({ onClick, children }) {
return <button onClick={onClick}>{children}</button>;
}
// Counter.js (использует Button)
function Counter() {
const [count, setCount] = useState(0);
return <Button onClick={() => setCount(count + 1)}>Count: {count}</Button>;
}
Код должен быть понятным не только мне, но и другим разработчикам.
Понятные имена переменных и функций. Вместо
x
→ userAge
, вместо doSmth()
→ calculateTotalPrice()
. Меньше вложенности. Вместо кучи
if
и else
, лучше использовать early return
. Разбиение кода на модули. Один файл = одна зона ответственности.
function getDiscountedPrice(price, discount) {
if (discount <= 0) return price;
return price - price * (discount / 100);
}
В зависимости от сложности приложения нужно правильно управлять состоянием:
Локальное состояние –
useState
(React), ref
(Vue) для простых данных внутри компонента. Глобальное состояние – Redux, MobX, Zustand, Pinia, Context API – когда данные нужны многим компонентам.
Серверное состояние – React Query, SWR – когда данные приходят с API и их нужно кешировать.
DRY (Don't Repeat Yourself) – не повторяем код, используем функции, хуки, компоненты.
SOLID – например, принцип единственной ответственности (Single Responsibility Principle) гласит, что каждый компонент или функция должны решать только одну задачу.
function sendEmailAndSaveToDB(user) {
sendEmail(user.email);
saveUserToDatabase(user);
}
Лучше разделить логику
function sendEmail(email) { /* отправка письма */ }
function saveUserToDatabase(user) { /* сохранение в БД */ }
function registerUser(user) {
sendEmail(user.email);
saveUserToDatabase(user);
}
TypeScript помогает избежать ошибок и делать код предсказуемым.
type User = {
id: number;
name: string;
};
function getUserName(user: User): string {
return user.name;
}
ESLint + Prettier → автоформатирование и проверка стиля.
JSDoc/TypeScript → документация функций и типов данных.
Storybook → для документирования UI-компонентов.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥1😁1💊1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊10👍3🔥2