TL;DR
Сеньор-разработчик отличается не столько знанием фреймворков, сколько архитектурной дисциплиной: продуманной композицией компонентов, грамотным управлением побочными эффектами и осознанным выбором абстракций. Разберём конкретные паттерны и инструменты, которые демонстрируют глубину понимания.
Введение: Beyond Hello World
Когда junior сосредоточен на “как сделать”, senior думает о “как не сломать”. Разница проявляется в мелочах: от обработки edge-кейсов до проектирования системы, которая не треснет при первом же требовании продукт-менеджера. Рассмотрим индикаторы профессионализма через призму React-экосистемы.
1. State Management: Когда Context уже недостаточно
Показательный пример — выбор стейт-менеджмента не по популярности, а по domain-логике:
// Не просто Zustand, а с гранулярной подпиской
const useUserPreferences = create<UserPreferences>()((set) => ({
theme: 'light',
updateTheme: (theme) => set({ theme }),
}));
// В компоненте:
const theme = useUserPreferences((state) => state.theme);
Почему это senior:
- Избегание ненужных ререндеров через селекторы
- Чёткое разделение read/write операций
- Декларативная типизация (не
any!)
2. Эффекты как first-class citizen
Типичный антипаттерн junior — useEffect везде, где нужно “что-то сделать”. Альтернатива:
// Кастомный хук для аналитики
function useAnalyticsEffect(event: AnalyticsEvent, deps: DependencyList) {
const analytics = useAnalytics();
useEffect(() => {
analytics.track(event);
}, [analytics, ...deps]);
}
// Использование:
useAnalyticsEffect('page_view', [pathname]);
Что это показывает:
- Инкапсуляция побочных эффектов
- Явные зависимости вместо скрытых coupling
- Возможность мока в тестах
3. TypeScript как дизайн-система
Senior использует TS не для аннотаций, а для проектирования:
// Вместо примитивов — branded types
type UserId = string & { __brand: 'userId' };
type Email = string & { __brand: 'email' };
// Валидация при runtime (Zod + type narrowing)
const UserSchema = z.object({
id: z.string().transform((val) => val as UserId),
email: z.string().email().transform((val) => val as Email),
});
Почему важно:
- Предотвращает логические ошибки (UserId ≠ OrderId)
- Документирует intent через типы
- Интеграция с backend через shared types
4. Тестирование: не только Jest
Профессионал тестирует не только рендер, но и поведение:
// Интеграционный тест с MSW
test('loads user data', async () => {
server.use(
rest.get('/api/user', (req, res, ctx) => {
return res(ctx.json(mockUser));
})
);
render(<UserProfile />);
await waitFor(() => {
expect(screen.getByText(mockUser.name)).toBeInTheDocument();
});
});
Что ценного:
- Тестирование user flow, а не изолированных компонентов
- Использование production-like API
- Отсутствие моков реализации (тестирование интерфейсов)
5. Перформанс как feature
Оптимизации не по шаблону, а по данным:
// Динамический импорт + Suspense границы
const HeavyChart = React.lazy(() => import('./HeavyChart'));
function Dashboard() {
return (
<ErrorBoundary>
<Suspense fallback={<ChartSkeleton />}>
<HeavyChart />
</Suspense>
</ErrorBoundary>
);
}
Критерии senior-подхода:
- Загрузка по необходимости (LCP-оптимизация)
- Graceful degradation при ошибках
- Измерение через Web Vitals, а не предположения
Практическое применение
Собираем всё вместе в реальном сценарии — форма с валидацией:
function CheckoutForm() {
const { register, handleSubmit } = useForm<CheckoutData>({
resolver: zodResolver(CheckoutSchema),
});
useAnalyticsEffect('checkout_viewed', []);
const { mutateAsync } = useCheckoutMutation();
const onSubmit = handleSubmit(async (data) => {
await mutateAsync(data);
});
return (
<form onSubmit={onSubmit}>
<Input {...register('email')} />
<AsyncSubmitButton loadingText="Processing..." />
</form>
);
}
Что здесь senior-grade:
- Сквозная типизация от UI до API
- Изолированные side effects
- Оптимистичные UI-обновления через React Query
- Соответствие a11y (не просто div + onClick)
Заключение: Идеология против синтаксиса
Настоящий senior — не тот, кто знает все хуки React, а тот, кто понимает, когда их не использовать. Профессионализм измеряется не количеством зависимостей в package.json, а способностью объяснить, почему в проекте их именно столько. Ваш код — это автопортрет: пусть в нём читается не только умение гуглить, но и инженерная культура.
Источник: https://www.reddit.com/r/webdev/comments/1qifdm5/what_are_things_that_you_see_and_make_you_say/