Какие архитектурные решения React навязывает вокруг rendering, state, routing, styling, data loading или deployment?
React навязывает компонентную модель и Virtual DOM, но не диктует роутинг, стейт и стилизацию — их выбирает команда. Server Components (Next.js) добавляют жёсткие ограничения: CSS-in-JS не работает, data loading переезжает на сервер.
Архитектурные решения, которые React навязывает
React — это «view library», но вокруг него сложились устойчивые архитектурные паттерны. Разберём по осям.
Rendering
React использует Virtual DOM и reconciliation через алгоритм Fiber. Приложение рендерится либо на клиенте (CSR), либо на сервере (SSR/SSG через Next.js). С React 18 появился Concurrent Mode: startTransition, Suspense и Server Components меняют модель рендеринга радикально.
// Server Component (Next.js App Router) — рендерится только на сервере
// app/jobs/page.tsx
export default async function JobsPage() {
const jobs = await db.query("SELECT * FROM jobs LIMIT 20");
return <JobList jobs={jobs} />; // нет JS на клиенте
}
// Client Component — рендерится и на сервере (hydration), и на клиенте
"use client";
export function SearchBar() {
const [q, setQ] = useState("");
return <input value={q} onChange={(e) => setQ(e.target.value)} />;
}
State Management
React предоставляет useState, useReducer и Context API. Для сложного глобального состояния экосистема предлагает Zustand, Jotai, Redux Toolkit. Для серверного состояния — TanStack Query или SWR.
Routing
React сам роутинг не включает. Варианты: Next.js App Router (файловая система), React Router v7, TanStack Router. Каждый навязывает свою структуру папок и модель data loading.
Styling
React не диктует подход: CSS Modules, Tailwind CSS, styled-components, Emotion, CSS-in-JS — всё работает. Но Server Components несовместимы с CSS-in-JS (runtime injection), что подталкивает к Tailwind или CSS Modules.
Data Loading
// Next.js: data loading в Server Component (нет waterfall)
async function ProductPage({ params }: { params: { id: string } }) {
const [product, reviews] = await Promise.all([
fetchProduct(params.id),
fetchReviews(params.id),
]);
return <Product data={product} reviews={reviews} />;
}
// TanStack Query: клиентский data fetching
function useJobs() {
return useQuery({
queryKey: ["jobs"],
queryFn: () => fetch("/api/jobs").then((r) => r.json()),
staleTime: 60_000,
});
}
Deployment
Чистый React (Vite) деплоится как статика (CDN). Next.js требует Node.js-сервер или Vercel/Netlify с edge-функциями. Server Components и ISR добавляют требования к инфраструктуре.
Подводные камни
- Server vs Client Components: смешивание без понимания границы «use client» приводит к тому, что серверный код попадает в bundle или клиентский стейт теряется при hydration.
- CSS-in-JS несовместим с RSC: styled-components и Emotion не работают в Server Components из-за runtime injection — нужна миграция на Tailwind или CSS Modules.
- Waterfall запросов: последовательные
useEffectдля data fetching создают «request waterfall» — фиксируется черезPromise.allв Server Component или parallel routes. - Hydration mismatch: расхождение между SSR HTML и клиентским рендером ломает приложение и дорого диагностируется.
- Context как антипаттерн для частых обновлений: Context API ре-рендерит всех подписчиков при любом изменении — для high-frequency updates нужен Zustand или Jotai.
- Роутинг завязан на фреймворк: смена Next.js App Router на Pages Router или React Router требует рефакторинга data loading.
- Bundle size при неправильном tree-shaking: импорт всей библиотеки вместо отдельных модулей раздувает клиентский JS.
What hurts your answer
- Знать термины React, но не понимать связи между абстракциями
- Объяснять поведение через отдельные примеры вместо причинной модели
- Не связывать mental model с диагностикой ошибок
What they're listening for
- Понимает ключевые абстракции React
- Может предсказывать поведение системы через mental model
- Связывает модель с debugging и production decisions