Руслан Куянец | Reactify – Telegram
Руслан Куянец | Reactify
5.85K subscribers
703 photos
52 videos
39 files
286 links
Я IT-специалист, ментор и основатель проекта YeaHub и сообщества Reactify. Здесь рассказываю про Frontend и IT.

Менторство:
https://reactify.ru

YouTube канал:
https://youtube.com/@reactify-it

YeaHub:
https://yeahub.ru/

Связь:
@ruslan_kuyanets
Download Telegram
🐝 Собеседование в компании Билайн

Позиция Middle Frontend Разработчик

1. Разница между WebSocket и SSE?
2. Разница между юнит-тестами и интеграционными тестами?
3. Допишите код хука и его типы:

type UseArrayActions = {
push: (item) => void,
removeByIndex: (index) => void
}

export function useArray(initialValue): { value } & UseArrayActions {
const [value, setValue] = useState(initialValue);

const push = (item) => setValue();
const removeByIndex = (index) => setValue();

return { value, push, removeByIndex };
}


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

console.assert( findUniq(['a', 'a Aa', 'ab a', 'AA a']) === 'ab a' );
console.assert( findUniq(['ab', 'a Aa', 'ab a', 'bAA a']) === 'a Aa' );
console.assert( findUniq([1,2,1,1]) === 2 );
console.assert( findUniq(['aBca', 'ac b', 'bac', 'fO o', 'bca', 'cabaccBA', ' Ccba']) === 'fO o' );

function findUniq(strings) {
???
}


5. Объясните, что произойдет при выполнении следующего кода:

const Andrey = {
name: 'Андрей',
surname: 'Малахов',
city: {
name: 'Москва'
},
}

const Genadius = {
name: 'Генадий',
surname: 'Малахов',
city: Andrey.city,
}

Genadius.city.name = 'Санкт-Петербург'


6. В каких случаях может выполниться “something code”?

const checkIntervalMs = 2000;
const toleranceMs = 2000;
let lastCheckStamp: number = null;

setInterval(
() => {
const now = Date.now();
if (lastCheckStamp && now - lastCheckStamp > checkIntervalMs + toleranceMs){
//something code
}
lastCheckStamp = now;
},
checkIntervalMs
);


7. Что такое Server-Sent Events?
8. Опыт работы с постоянным соединением через WebSocket?
9. Что такое Event Loop?
10. Что происходит при вводе адреса в адресной строке и нажатии Enter?
11. Что такое чистая функция?

#interview
👍29🔥65
👩‍💻 Инжектирование эндпоинтов в RTK Query и организация API в отдельных файлах

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

Организация базового API

Рекомендуется создать отдельный файл для базового API, который будет содержать общие настройки, такие как baseQuery, reducerPath и другие параметры, а также общие эндпоинты.


// baseApi.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const baseApi = createApi({
reducerPath: 'baseApi',
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
tagTypes: ['User', 'Post'], // Определяем типы тегов для инвалидации кэша
});

export default baseApi;


Создание эндпоинтов для различных сущностей

Теперь вы можете создать отдельные файлы для каждой сущности, добавляя в них необходимые эндпоинты и используя базовый API.


// userApi.js
import baseApi from './baseApi';

// injectEndpoints автоматически добавит эндпоинты к baseApi
const userApi = baseApi.injectEndpoints({
endpoints: (builder) => ({
fetchUsers: builder.query({
query: () => 'users',
providesTags: ['User'], // Указываем, что этот запрос использует тег 'User'
}),
addUser: builder.mutation({
query: (newUser) => ({
url: 'users',
method: 'POST',
body: newUser,
}),
invalidatesTags: ['User'], // Инвалидируем кэш для 'User'
}),
}),
overrideExisting: false, // Не переопределяем существующие эндпоинты
});

export const { useFetchUsersQuery, useAddUserMutation } = userApi;
export default userApi;

Пример эндпоинтов для постов

// postApi.js
import baseApi from './baseApi';

// injectEndpoints автоматически добавит эндпоинты к baseApi
const postApi = baseApi.injectEndpoints({
endpoints: (builder) => ({
fetchPosts: builder.query({
query: () => 'posts',
providesTags: ['Post'], // Указываем, что этот запрос использует тег 'Post'
}),
addPost: builder.mutation({
query: (newPost) => ({
url: 'posts',
method: 'POST',
body: newPost,
}),
invalidatesTags: ['Post'], // Инвалидируем кэш для 'Post'
}),
}),
overrideExisting: false, // Не переопределяем существующие эндпоинты
});

export const { useFetchPostsQuery, useAddPostMutation } = postApi;
export default postApi;


Инжектирование эндпоинтов в RTK Query позволяет вам создавать гибкую и масштабируемую архитектуру для работы с несколькими сущностями. Разделение логики API на отдельные файлы помогает поддерживать чистоту и порядок в коде, а использование базового API упрощает добавление новых эндпоинтов. Такой подход способствует улучшению читаемости и поддерживаемости вашего приложения.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍235🔥4
🎤 Задание с лайвкодинга в Авито

Проанализируйте код и определите, что будет выведено в консоли.

(function () {
function modifyItemData(price, platform) {
price.rub = 5000;
platform = 'iOS';
isModified = true;

function printItemData() {
console.log(price); // ?
console.log(platform); // ?
console.log(isModified); // ?
}

return printItemData;
}

let price = { rub: 3500 };
let platform = 'Android';
let isModified = false;

const printItemData = modifyItemData(price, platform, isModified);

console.log(price); // ?
console.log(platform); // ?
console.log(isModified); // ?

price = { usd: 100 };
platform = 'Web';
isModified = null;

printItemData();
})();

Вопросы:
1. Почему price изменяется, а platform — нет?
2. Как работает область видимости переменной `isModified`?


#собеседование #лайвкодинг
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥7💯1
Фронтенд в картинках — просто, наглядно и понятно. Новые знания в компактном формате каждый день.

Присоединяйтесь: @FrontendPortal
👍24🔥43💯1
👩‍💻 Проектирование таблицы в React: SOLID, IoC и Render Props

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

Проблема:
Если делать отдельный компонент под каждую сущность (UsersTable, ProductsTable), получим дублирование кода. Если запихать всю логику в один компонент — он превратится в монстра с кучей if-else.

Решение:
Делаем единную таблицу, но гибкую. Вместо хардкода данных и столбцов, выносим рендеринг наружу.

Какие техники применяем?
✔️ Render Props – Передаём renderRow и renderHeader как пропсы. Внутри Table только разметка, логика рендеринга — снаружи.

✔️ Принцип открытости/закрытости – Если для товаров нужна иконка валюты, а для пользователей — аватарка, не лезем внутрь Table, а просто рисуем нужное в переданной функции.

✔️ Dependency Injection – Зависимости (рендер-функции) приходят через пропсы. Можно подставить любую логику без изменений самого компонента.

✔️ Инверсия управления (IoC) – Table не знает, что в нём будет. Управление содержимым — у родителя.

✔️ Паттерн "Стратегия" – renderRow и renderHeader — это стратегии отображения. Подменяем их под задачу.

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

Если тема интересна, сделаю серию постов про другие типовые компоненты: модалки, фильтры, карточки. Как вам идея?


#react #solid #patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍39🔥127
🎂 Мой год перемен

В 27 лет я был в найме, только пробовал себя в менторстве, YeaHub существовал на уровне "в свободное время что-то пилим, одну страницу делаем месяц". На YouTube было 4000 подписчиков, в Telegram3000. Только родилась дочь, работы — море, пахал 24/7 без выходных.

Год спустя, в 28, всё иначе.

Я ушел из найма и полностью погрузился в свой проект. Сейчас в нём — 2000 зарегистрированных пользователей, 40 000 посещений за 5 месяцев, ежедневно платформу посещают 500–800 человек. Сеть каналов YeaHub выросла до 6000+ подписчиков. YouTube приближается к 10 000, Telegram5200.

За год для учеников я создал полноценный курс-роадмап: от основ HTML/CSS до продвинутых тем вроде Docker и CI/CD. Записал 150+ уроков, собрал базу гайдов и материалов. В мае выйдет бесплатный курс по JS DOM API на YouTube – я продолжаю делиться знаниями бесплатно.

Но главное — люди.

За этот год я обучил (и продолжаю обучать) больше 150 человек. Сообщество учеников и выпускников — уже 130+ человек. Помог трудоустроиться более 30 ребятам. Познакомился с крутыми ребятами — блогерами, менторами, экспертами. Вступил в сильные IT-сообщества. Прочувствовал мощь нетворкинга и силу окружения. Стал лучше, пересмотрел взгляды, прокачал мышление.

А ещё — это самый тёплый день рождения в моей жизни.

Утро началось с 40+ поздравлений от учеников. Жена с дочкой встретили меня с тортиком — не сдержался, прослезился 🥹. Писали коллеги, друзья, знакомые — столько тёплых слов, благодарностей и пожеланий.

Когда тебя так искренне поздравляют, когда благодарят за помощь, вдохновение и поддержку — понимаешь: я на правильном пути.

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

И знаю: впереди — ещё больше свершений. 💪
🔥67👍279🤝2
💭 Кто такой мидл во фронтенде?

Наверное, каждый из нас слышал, что первые 2-3 месяца на реальной работе бустят новичка на 300-400%. То есть, со временем эффективность обучения снижается. Условно: если учишься 6 месяцев и 1 год, по логике год обучения должен делать тебя в 2 раза круче. Но не всё так однозначно.

Тут вступает принцип Парето — 20% усилий дают 80% результата. Первые полгода ты поглощаешь знания, как голодный, а дальше — упорство уже не даёт такого же мощного прироста. Можно, конечно, выжимать соки из каждого месяца: строить чёткий план, качать насмотренность, разбирать архитектуру, пилить проекты. Но без реальной работы прогресс будет медленнее.

Зато как только попадаешь в продакшн — бац! — и тебя накрывает жесткий буст. Ты начинаешь по-новому смотреть на код, у тебя формируется логика работы. Это неизбежный этап — он был у меня, будет и у тебя.

👩‍💻 Как учиться после освоения стека?

Когда база (HTML, CSS, JS, фреймворк) уже есть, важно не застрять в вечном ученичестве. Вот что реально прокачает тебя дальше:

1. Жёсткая практика
Повторяешь за авторами — берёшь проекты с YouTube, но не просто копируешь, а вдумчиво смотришь: как человек дробит компоненты, как выстраивает логику, как думает.

Делаешь своё — без копирования, с нуля: дизайн, API, свои фичи. Чередуешь: один проект по видео → один свой.

Большой пет-проджект — как только чувствуешь, что можешь писать код без постоянных гуглений, запускаешь монстра: куча страниц, запросов, сложные состояния.

2. Архитектура и продакшн-сетап
Когда компоненты даются легко, пора качать уровень проекта:
- Сборка (Webpack/Vite) — настроить самому, а не на create-react-app.
- UI Kit — завести Storybook, сделать переиспользуемые компоненты.
- Деплой и CI/CD — выложить на Vercel/Netlify, или настроить VPS, настроить автотесты.
- Тесты — хотя бы пару, чтобы понимать, как они работают.

На собесах спрашивают:
"Был ли у вас UI Kit?"
"Как настраивали деплой?"
"Писали ли тесты?"


Мидл должен шарить за проект, на котором работал.

3. Конференции и реальные кейсы
Чтобы не быть "зелёным", надо расширять кругозор:
- Смотришь доклады из Яндекса, Тинькоффа, Ozon — как они решают реальные проблемы.
- Узнаёшь, как мигрируют между фреймворками, как оптимизируют загрузку, как выстраивают процессы.

Даже 2-3 конференции дадут темы для собеса и покажут, что ты в теме.

Сколько времени займёт?
- Базовый стек — ~5 месяцев.
- 3-4 проекта по видео и своих — 1 месяц.
- Сборка, Storybook, CI/CD — 2-3 недели.
- Свой большой проект — 1 месяц.
- Конференции — 1 неделя.

Итог: ты будешь ориентироваться в рабочем проекте, сможешь писать код уверенно и не потеряешься в продакшне.

❗️ Главное — не засиживаться

Можно стать сильнее мидла с 4 годами опыта, если он все эти годы просто штамповал код и не развивался.

Учись осознанно, качай продакшн-скиллы, смотри в сторону реальных задач — и тогда буст не заставит себя ждать.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍33🔥15💯4
👩‍💻 Разработка UI Kit: создание компонента Button

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

1️⃣ Во-первых, UI Kit обеспечивает визуальную и функциональную согласованность интерфейса. Когда десятки или сотни экранов используют одни и те же компоненты
2️⃣ Во-вторых, разработка ускоряется в разы — вместо создания элементов с нуля, команда использует готовые решения.
3️⃣ В-третьих, значительно упрощается поддержка и масштабирование: изменения в дизайн-системе вносятся в одном месте, а применяются во всём проекте.

[Картинка 1: Пример Storybook]

UI Kit — это не просто коллекция кнопок и полей ввода. Это комплексная система, включающая:
- Базовые компоненты интерфейса (кнопки, формы, переключатели)
- Типографику и иерархию текста
- Цветовую палитру с семантическим значением цветов
- Систему отступов и размеров
- Состояния элементов (активное, неактивное, hover, focus)

[Картинка 2 и 3: Дизайн в Figma]

🛡 Основные принципы разработки компонентов UI Kit
При создании компонентов для UI Kit необходимо придерживаться нескольких фундаментальных принципов

1. Семантическая корректность
Каждый компонент должен максимально точно отражать свою суть на уровне HTML-разметки. Кнопка — это <button> или <input type="button">, ссылка — <a>, поле ввода — <input> или <textarea>. Это важно не только для доступности (accessibility), но и для правильной работы в различных контекстах (например, в формах или при навигации).

2. Полнота свойств
Компонент должен поддерживать все стандартные HTML-атрибуты соответствующего элемента. Для кнопки это включает type (button, submit, reset), disabled, autofocus и другие.

3. Управляемость извне
Компонент не должен содержать внутреннюю логику состояния (где это возможно). Все состояния (активное, неактивное, загружающееся) должны управляться через пропсы. Это делает компонент предсказуемым и легко интегрируемым в любую архитектуру.

4. Принцип открытости/закрытости
Компонент должен быть закрыт для модификаций (его базовое поведение нельзя изменить), но открыт для расширения. На практике это означает:
- Возможность добавления классов через className
- Возможность передачи произвольных атрибутов
- Гибкость в контенте через children

5. Единый источник правды
Изменение компонента в UI Kit должно автоматически отражаться во всех местах его использования. Это требует тщательного проектирования API компонента на этапе создания, чтобы избежать необходимости "ветвления" логики в будущем.

🔒 Архитектура UI Kit в проекте
Оптимальная структура для UI Kit в проекте выглядит следующим образом:

src/
ui/
Button/
Button.tsx # React-компонент
Button.stories.tsx # Документация в Storybook
Button.test.tsx # Тесты компонента
Button.module.css # Стили компонента
Input/ # Аналогичная структура для других компонентов
...
styles/
variables.css # CSS-переменные (цвета, отступы, шрифты)
typography.css # Типографика
animations.css # Анимации
global.css # Глобальные стили


🖥 Реализация компонента Button для UI Kit
Перед разработкой тщательно изучаем макеты и выделяем все варианты кнопок: Варианты по стилю, Размеры, Состояния, Дополнительные требования (иконки, текст).

[Картинка 4: Компонент Button]

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

[Картинка 5: CSS-переменные]

Создаем подробные TypeScript-интерфейсы: Объединение с нативными атрибутами button и a, Поддержка всех стандартных HTML-атрибутов, Четкое разделение кастомных и стандартных пропсов

[Картинка 6: Типизация кнопки]

Далее создаем сторисы для всех вариантов: Основной вид, Все состояния, Примеры с иконками, Вариант как ссылки

#ui #storybook #button #react
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24👍124🤝2