Irbisa · Cheatsheet
Patterns & Architecture
Composition patterns, compound components, render props and HOCs, error boundaries, portals, folder structure, design systems, monorepos
Is the container/presentational component split still useful now that we have hooks?
How do the SOLID principles apply to React components and hooks?
import type { ReactNode } from 'react'; // I: ask for the fields you use, not the whole `user`function Avatar({ name, src }: { name: string; src: string }) { return <img src={src} alt={name} className="avatar" />;}…How do you do dependency injection in React, for example to swap the API client in tests or Storybook?
import { createContext, use, type ReactNode } from 'react'; interface Api { getUser(id: string): Promise<User>; saveUser(user: User): Promise<void>;}…How do you avoid prop drilling without moving everything into global state?
import type { ReactNode } from 'react'; // before: Page -> Layout -> Sidebar -> UserMenu all forward `user`// after: Layout only places what it is givenfunction Layout({ sidebar, children }: { sidebar: ReactNode; children: ReactNode }) { return (…What are compound components and how do you build one with context?
import { createContext, use, useState, type ReactNode } from 'react'; const TabsContext = createContext<{ active: string; setActive: (id: string) => void } | null>(null); function useTabs() { const ctx = use(TabsContext);…What is a render prop, and when would you still choose one over a custom hook?
import { useState, type ReactNode } from 'react'; interface SelectProps<T> { items: T[]; getKey: (item: T) => string; renderOption: (item: T, state: { selected: boolean }) => ReactNode;…What is a higher-order component, what problems does it have, and what replaced it?
import type { ComponentType } from 'react';import { Navigate } from 'react-router'; function withAuth<P extends object>(Wrapped: ComponentType<P>) { function WithAuth(props: P) { const { user, isLoading } = useAuth();…What is a headless component or headless UI library (Radix, React Aria, TanStack Table), and why would you build on one?
import { useId, useState } from 'react'; // Behaviour and ARIA only: no markup, no stylesfunction useDisclosure(initialOpen = false) { const [open, setOpen] = useState(initialOpen); const panelId = useId();…What is an error boundary, and which errors does it not catch?
import { Component, type ErrorInfo, type ReactNode } from 'react'; interface Props { fallback: ReactNode; children: ReactNode }interface State { hasError: boolean } class ErrorBoundary extends Component<Props, State> {…Find the bug: when
api.save()fails, the error boundary fallback never appears and the console shows an unhandled rejection.function SaveButton() { async function handleClick() { await api.save(); // rejects when the server is down } return <button onClick={handleClick}>Save</button>;} function Editor() { return ( <ErrorBoundary fallback={<p>Something went wrong</p>}> <SaveButton /> </ErrorBoundary> );}What is a portal, and when do you need one?
import type { ReactNode } from 'react';import { createPortal } from 'react-dom'; interface ModalProps { open: boolean; onClose: () => void;…What does this log when the user clicks the button rendered through a portal?
import { createPortal } from 'react-dom'; function App() { return ( <div onClick={() => console.log('App div')}> <Popup /> </div> );} function Popup() { return createPortal( <button onClick={() => console.log('button')}>Open</button>, document.body, );}How would you structure folders in a large React app?
src/ app/ providers, router, global styles pages/ route components: compose features, no logic features/ checkout/ api.ts…Review this component as you would in a code review: what problems do you see, and in what order would you raise them?
function TeamMembers({ teamId, onSelect }: { teamId: string; onSelect: (user: User) => void }) { const [users, setUsers] = useState<User[]>([]); const [query, setQuery] = useState(''); const [visible, setVisible] = useState<User[]>([]); useEffect(() => { fetch(`/api/teams/${teamId}/users`).then((res) => res.json()).then(setUsers); }, []); useEffect(() => setVisible(users.filter((u) => u.name.includes(query))), [users, query]); return ( <div> <input value={query} onChange={(e) => setQuery(e.target.value)} /> {visible.map((u) => <div key={u.id} onClick={() => onSelect(u)}>{u.name}</div>)} </div> );}How do you design a reusable component that works both controlled and uncontrolled?
import { useState, type ReactNode } from 'react'; function useControllableState<T>(value: T | undefined, defaultValue: T, onChange?: (next: T) => void) { const [inner, setInner] = useState(defaultValue); const isControlled = value !== undefined; const current = isControlled ? value : inner;…Where do you place error boundaries in an app, and how do they work with Suspense and retry?
import { Suspense, type ReactNode } from 'react';import { ErrorBoundary } from 'react-error-boundary';import { useLocation } from 'react-router'; function RouteShell({ children }: { children: ReactNode }) { const { pathname } = useLocation();…How do you set up error monitoring for a production React app so that the reports are readable and actionable?
import * as Sentry from '@sentry/react';import { createRoot } from 'react-dom/client'; Sentry.init({ dsn: import.meta.env.VITE_SENTRY_DSN, release: import.meta.env.VITE_GIT_SHA, // ties every event to one deploy…How do you stop features from importing each other's internals, and what are the pitfalls of barrel files?
// eslint.config.jsexport default [ { files: ['src/**/*.{ts,tsx}'], rules: { 'no-restricted-imports': ['error', {…When does a monorepo make sense for React projects, and how do you set one up?
{ "name": "@acme/ui", "version": "0.0.0", "private": true, "type": "module", "exports": {…How would you upgrade a large app from React 18 to React 19, and what tends to break?
# 1. React 18.3 is 18.2 plus a warning for every API React 19 removesnpm install react@18.3 react-dom@18.3# run the app and the tests, fix every warning # 2. Codemods for the removed APIs and for the type changesnpx codemod@latest react/19/migration-recipe…