react style guide
react best practices
react conventions
react development
code standards

React Style Guide: An Opinionated Reference for 2026

React Style Guide: An Opinionated Reference for 2026

You probably have one right now.

A React codebase that started clean, shipped fast for a few sprints, and then slowly picked up three button patterns, four API-fetching styles, two ways to name hooks, and a handful of components that nobody wants to touch before release day. Reviews drift into preference arguments. Accessibility gets treated like a cleanup task. Styling decisions spread across CSS Modules, utility classes, and ad hoc runtime styling with no clear boundary for when each is acceptable.

That's when a React style guide stops being documentation theater and starts being operational infrastructure.

A common error involves treating the React style guide as a static markdown file. That fails almost immediately. Rules people have to remember by hand don't scale. A useful guide has to live in the repo, in linting, in formatting, in component templates, in testing defaults, and in review habits. It should enforce modern React patterns, especially hooks, composition, and pure rendering, instead of repeating class-component-era advice that no longer solves prevalent problems.

The need is obvious at scale. A 2024 market analysis reported that the React repository had more than 228,000 GitHub stars and 46,000 forks, while npm trends showed React receiving millions of weekly downloads as of October 2023, which reflects a massive developer base working in codebases where consistency matters for maintainability (React market analysis).

A good React style guide doesn't reduce creativity. It removes repeated low-value decisions so teams can spend judgment where it matters: product behavior, architecture, performance, and accessibility.

Introduction Why Every React Project Needs an Opinionated Style Guide

An opinionated React style guide solves a simple problem. Entropy wins by default. If you don't define how components are named, where hooks live, how styles are applied, and what counts as accessible UI, every developer fills in the blanks differently.

That doesn't hurt much in a small repo. It hurts when onboarding takes longer because every feature has its own shape, when refactors stall because side effects hide inside presentational components, and when a design-system component looks polished but breaks keyboard navigation in the product app.

What an opinionated guide should actually do

A useful guide should answer questions developers hit every day:

  • Component boundaries: When does a component become too large?
  • Hook extraction: What belongs in a custom hook and what should stay local?
  • Styling choices: When is a utility class enough, and when do you need scoped CSS?
  • Accessibility enforcement: Which checks block a pull request, and which require manual review?
  • Structure: Where do tests, stories, providers, and feature-specific types belong?

If the document doesn't answer those questions, people invent answers during delivery pressure.

Practical rule: If a standard can be enforced by tooling, don't leave it as “team preference.”

A living system, not a policy document

The strongest React teams don't rely on memory. They rely on a stack that makes the preferred path the easiest path.

That usually means three foundations working together:

  • ESLint for code-quality and React rules
  • Prettier for formatting decisions nobody should debate
  • TypeScript for component contracts, prop design, and safer refactors

Many public style guides often fall short. They list ideals, but they don't give teams an enforcement model. An opinionated React style guide should behave more like a development environment than a handbook. It should shape daily decisions automatically.

That's also why modern guidance matters more than historical nostalgia. Teams building with hooks and composition need a guide that matches how React is written today, not one built around legacy patterns that linger because they were once common.

Foundational Tooling for Automated Consistency

The React style guide ecosystem has deep roots in community standards. A major milestone was the broad adoption of Airbnb's React/JSX Style Guide, which formalized rules such as one component per file, JSX syntax conventions, double quotes in JSX attributes, and avoiding array indices as keys. Those conventions still echo through modern tooling and isolated component workflows today (Airbnb React/JSX Style Guide).

That history matters, but the implementation has changed. In modern projects, the goal isn't to memorize a style guide. The goal is to make violations expensive and correct patterns automatic.

The baseline stack

Use these responsibilities clearly:

  • Prettier owns formatting. Spacing, semicolons, quotes, line width, trailing commas. End the argument.
  • ESLint owns correctness and React usage. Hooks rules, import hygiene, dead code, accessibility linting, and architectural guardrails.
  • TypeScript owns interfaces and contracts. Props, return types when useful, API payloads, and shared domain types.

When teams blur these boundaries, configs become noisy and developers stop trusting the feedback. Keep each tool narrow and predictable.

For startups building with small teams, access control and collaboration matter too. If you're standardizing workflow around pull requests, repos, and CI from day one, it's worth checking options to get free GitHub for startups so the operational side of the style guide isn't blocked by tooling cost.

Starter ESLint and Prettier Configuration for React + TypeScript

File Configuration
.eslintrc.cjs module.exports = { root: true, env: { browser: true, es2022: true, node: true }, parser: '@typescript-eslint/parser', parserOptions: { ecmaVersion: 'latest', sourceType: 'module', ecmaFeatures: { jsx: true } }, settings: { react: { version: 'detect' } }, plugins: ['react', 'react-hooks', '@typescript-eslint', 'jsx-a11y', 'import'], extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react-hooks/recommended', 'plugin:@typescript-eslint/recommended', 'plugin:jsx-a11y/recommended', 'plugin:import/recommended', 'plugin:import/typescript', 'prettier'], rules: { 'react/react-in-jsx-scope': 'off', 'react/prop-types': 'off', 'react/jsx-boolean-value': ['error', 'never'], 'react/self-closing-comp': 'error', 'react/jsx-sort-props': 'off', 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], 'import/order': ['error', { 'newlines-between': 'always', alphabetize: { order: 'asc', caseInsensitive: true } }] } };
.prettierrc.json { "semi": true, "singleQuote": true, "trailingComma": "all", "printWidth": 100 }

What this stack should enforce in practice

A good baseline catches common drift early:

  • Hooks misuse: calling hooks conditionally, in loops, or from the wrong place
  • Import sprawl: mixed ordering and accidental dependency tangles
  • Accessibility misses: invalid markup and common JSX a11y issues
  • Formatting churn: reviews filled with whitespace noise instead of architectural feedback

Teams move faster when code review stops arguing about commas and starts catching real design mistakes.

I'd also add pre-commit formatting and CI lint checks as essential. If the repo accepts code that breaks local standards, the document is already losing to the pipeline.

Scalable File and Folder Structure Conventions

Many teams don't have a React problem. They have a navigation problem.

Type-based folder structures look tidy at first:

  • components/
  • hooks/
  • services/
  • types/
  • utils/

Then a single feature spreads across six directories, nobody can see its full surface area at once, and every change becomes a scavenger hunt. For large applications, I strongly prefer feature-based colocation.

A hand-drawn illustration showing a folder labeled Features containing subfolders for React components, hooks, and tests.

The structure that scales better

A feature-first layout keeps related files together:

src/
  features/
    user-profile/
      components/
        UserProfileCard.tsx
        UserProfileForm.tsx
      hooks/
        useUserProfile.ts
        useUpdateUserProfile.ts
      api/
        userProfileApi.ts
      types/
        userProfile.types.ts
      tests/
        UserProfileForm.test.tsx
      index.ts

This works because most maintenance work is feature-local, not type-local. A developer changing profile editing behavior should not jump between distant folders for component code, request logic, local types, and tests.

For systems that later split into federated apps, this structure also maps more naturally to bounded domains. If that's on your roadmap, React micro frontends become easier to reason about when feature ownership is already explicit.

Naming and export rules that reduce friction

Inside a feature, the conventions should be boring:

  • Components use PascalCase and file names match the exported component.
  • Hooks start with use and live near the feature they support unless they're cross-cutting.
  • Types stay local until proven shared. Don't move everything to a global types/ folder on day one.
  • Public entry points go through index.ts. Internal helpers don't need to be globally importable.

The key trade-off is duplication versus discoverability. Some local duplication is cheaper than a giant shared layer full of abstractions nobody owns.

Shared code should be extracted because multiple features need the same stable abstraction. It shouldn't be extracted because someone dislikes seeing similar code twice.

What not to do

Avoid these patterns if you want the React style guide to stay enforceable:

  • Global dumping grounds: utils/, helpers/, and common/ become junk drawers fast.
  • Deep nesting: if developers need five clicks to find a component, the structure is too clever.
  • Premature “shared” packages: centralization too early increases coupling and slows feature work.

A practical style guide values movement. Your file structure should help developers change one business capability at a time without loading the whole application into their head.

Modern Component Design and Naming Patterns

A component should do one job clearly. The moment it starts fetching data, transforming payloads, applying business rules, conditionally building styles, and rendering five UI states in one file, it stops being a component and becomes a merge-conflict generator.

Modern React makes this easier to avoid, but only if the style guide is explicit about boundaries.

React's own rules are the right anchor here. Components and Hooks should remain pure, side effects should stay out of render, props and state should be treated as immutable snapshots, and Hooks must be called only at the top level, never inside conditions or loops (React rules for purity and hooks).

Component naming and prop design

Use PascalCase for component names and make the filename match the exported component. That sounds basic, but its primary benefit is searchability and stable review language.

For props, define a TypeScript interface or type next to the component unless it's shared on purpose. Keep prop APIs narrow. A component with ten boolean flags usually signals unclear responsibilities.

Prefer this:

  • UserMenu
  • UserMenuProps
  • onSelect
  • isOpen

Avoid this:

  • user_menu_component
  • props: any
  • handleThing
  • showVariantA, showVariantB, showCompact, showInline

Composition beats configuration bloat

Many teams overbuild “flexible” components that turn into switch statements with markup attached. Composition ages better.

Instead of a single modal with endless mode flags, use a composable API:

  • Modal
  • Modal.Header
  • Modal.Body
  • Modal.Footer

That gives teams structure without forcing every use case through a giant prop matrix.

A good component API makes the common path obvious and the unusual path possible. It shouldn't require developers to read the implementation to use it safely.

Hard rules for render logic

These are essential in a practical React style guide:

  1. Never create components inside another component's render path unless there's a very specific reason and you understand the trade-off.
  2. Never mutate props or state objects directly.
  3. Never hide side effects inside computed JSX.
  4. Never mix fetching logic with purely presentational branches if extraction will clarify ownership.

The first rule matters more than teams think. Inline component creation can reset identity, make memoization less effective, and create confusing rerender behavior.

When to split a component

Split a component when one of these becomes true:

  • The file handles multiple business concerns.
  • A nested section has its own state and behavior.
  • You can name a subpart clearly.
  • Tests become awkward because too much setup is required.

Don't split just to make files shorter. Split when it gives the code a better shape.

A common agency pattern is container and presentational separation, but not dogmatically. If a component owns small local state and its UI, keeping them together is often fine. Extract when reuse, testability, or readability improves.

Pragmatic Rules for Hooks and State Management

Hooks gave React a cleaner model for sharing logic, but they also made it easier to scatter side effects across a codebase. A style guide should narrow the choices.

My baseline rule is simple. Keep state as close as possible to where it's used, but no closer. That prevents both prop-drilling panic and premature global stores.

A practical decision model for state

Use component state when the data is local to one screen element or interaction. Form inputs, accordion state, dialog visibility, and temporary filters usually belong here.

Use Context when several nearby components need stable shared access to the same value or service. Theme, authenticated user data that's already resolved, and feature-level controller objects can fit well.

Use a dedicated state library like Zustand or Redux Toolkit when you need predictable cross-feature coordination, developer tooling, or a clear model for asynchronous updates and derived state. If state changes need to be observed from many places, local state plus context often becomes opaque faster than teams expect.

Rules for core hooks

For useState:

  • Store minimal state. Derived values should usually be computed, not stored.
  • Prefer explicit shapes. A typed object beats vague nested structures.
  • Avoid state that mirrors props unless you're handling a deliberate controlled or uncontrolled pattern.

For useEffect:

  • Use it for synchronization, not general sequencing.
  • Don't put pure calculations in an effect. Compute them during render or with memoization if needed.
  • Clean up subscriptions, listeners, and timers.
  • Treat dependency warnings seriously. If the dependency array looks wrong, the design usually is.

For useContext:

  • Keep context values stable so consumers don't rerender unnecessarily.
  • Split contexts by concern instead of creating one giant application context.
  • Don't use context as a dumping ground for state that should remain local.

When to create a custom hook

Create a custom hook when the logic has a real unit of meaning.

Good candidates:

  • useUserProfile
  • useDebouncedSearch
  • useFocusTrap
  • useCheckoutValidation

Bad candidates:

  • useButton
  • usePage
  • useDataStuff

A custom hook should hide complexity, not just move code around. If the hook mostly wraps one local useState and only serves one component, extraction may hurt readability more than it helps.

What styling choices have to do with hooks

Teams often sneak styling work into hooks and state in ways that create churn. Theme toggles, visual variants, responsive state, and interaction state can become over-engineered fast.

A good React style guide should keep the split clear:

  • Static styles: prefer CSS Modules or Tailwind classes
  • Theme values that change often: prefer CSS variables
  • Behavioral state: manage it in React
  • Per-render style object churn: avoid unless there's a strong reason

That separation keeps hooks focused on behavior instead of becoming a second styling layer.

A Decisive Guide to Styling React Applications

Styling debates waste time because teams compare tools as identity choices instead of delivery trade-offs. The better question is narrower: which styling approach gives you consistency, maintainability, and acceptable runtime behavior for this product?

For large React codebases, Telerik's guidance aligns with what works in practice: minimize runtime overhead, avoid creating styled components inside render functions, centralize design tokens for colors, spacing, and typography, and prefer CSS Modules or Tailwind for static styles (Telerik React styling guide).

A hand-drawn educational diagram showing three common methods for styling components in React applications.

Comparing the main options

Approach Best use Main trade-off
CSS Modules Component-scoped static styles Slightly more context-switching between TSX and CSS
Tailwind CSS Fast UI development with shared utility vocabulary Markup can get noisy without discipline
Styled Components or similar CSS-in-JS Dynamic styling with strong component affinity More runtime cost and easier misuse in render paths

My recommendation for most product teams is straightforward. Use Tailwind when the team is comfortable with utility-first styling and the design system is tokenized well. Use CSS Modules when you want stronger separation between markup and styles or when designers and frontend developers collaborate closely in conventional CSS. Use runtime CSS-in-JS selectively, not as the default.

The rule that matters more than the library

The most important styling standard isn't the tool. It's the design token layer.

Define tokens for:

  • Color
  • Spacing
  • Typography
  • Border radius
  • Elevation
  • Interaction states

Without that layer, every styling approach degrades into local decisions. With it, teams can swap implementation details and still preserve consistency.

If motion is part of your component system, treat animation tokens and transition patterns as first-class rules too. That's where many style guides are thin. A practical reference on animations in React can help teams define those boundaries before motion becomes inconsistent from component to component.

Styling should express the design system. It shouldn't reinvent it one component at a time.

What to ban outright

I'd explicitly ban these in most projects:

  • Creating styled-component instances inside render functions
  • Hard-coded magic values for spacing and color
  • Multiple competing styling strategies in the same feature without reason
  • Component-specific accessibility states that bypass system tokens

The last one matters. Focus rings, error states, disabled states, and hover states should come from system rules, not improvisation. That's where style consistency and accessibility meet.

Operationalizing Accessibility in Your Workflow

Most React style guides mention alt text, ARIA roles, and keyboard basics. That's not the hard part. The hard part is making accessibility repeatable when multiple developers touch the same product every week.

That gap is real. Dynatrace's React style guide covers rules such as always including alt, using valid ARIA roles, and avoiding accessKey, but the bigger problem for many teams is turning those ideas into a workflow that holds under delivery pressure (Dynatrace React style guide).

Accessibility has to move upstream

Treat accessibility as a design-and-development standard, not a QA checklist. That means the React style guide should define:

  • Token rules for contrast-sensitive colors and visible focus states
  • Component API expectations for labels, descriptions, error messaging, and keyboard handling
  • Review rules for interactive controls, modals, menus, and async status feedback
  • Testing defaults for both automated and manual verification

If your style guide only says “remember accessibility,” it hasn't operationalized anything.

For teams building public-facing products or working in compliance-heavy spaces, it helps to formalize this as part of the engineering workflow. A broader guide on how to make a website accessible can complement the React-specific rules with product-level practices.

The workflow that actually works

A practical setup usually includes three layers.

First, linting. eslint-plugin-jsx-a11y should run locally and in CI so common issues are caught before review.

Second, component-level standards. Your shared components should make accessible usage easier than inaccessible usage. A button component shouldn't require developers to remember focus styling from scratch. A modal should already support focus management and escape behavior. Form components should expose label, hint, and error relationships cleanly.

Third, manual checks. Some accessibility failures only show up when a developer uses the interface.

Use a short review routine:

  1. Keyboard pass: Can you tab through it, activate controls, and close overlays?
  2. Focus pass: Is focus visible and moved intentionally after state changes?
  3. Screen reader sanity check: Are names, roles, and states understandable?
  4. Error-state check: Do invalid forms explain what happened and where?

Accessibility quality improves when teams attach it to component contracts and pull-request checks, not when they save it for the end of the sprint.

What a living style guide should mandate

I'd encode these rules directly:

  • Every interactive component must have a documented keyboard interaction model.
  • Focus-visible styling is required, not optional.
  • Design tokens must include accessible state variants.
  • Pull requests that introduce new UI patterns should include accessibility acceptance notes.

That turns accessibility from “best effort” into an engineering standard with ownership.

Effective Testing and Performance Optimization

Testing and performance discipline should reinforce the React style guide, not sit beside it. If your guide says components should be composable, pure, and accessible, your test strategy should verify those assumptions at the right level.

A hand-drawn pyramid illustration representing software testing levels with a stopwatch and the React logo.

A pragmatic React testing pyramid

For most applications, the sweet spot is:

  • Many unit tests for utilities and complex custom hooks
  • A strong middle layer of integration tests for components and feature flows with React Testing Library
  • A smaller set of end-to-end tests for critical user journeys

The mistake is putting too much weight at the top. Heavy browser tests are useful, but if every interaction requires a full-stack test to feel safe, your component boundaries are probably weak.

For example, unit-test a hook like useDebouncedSearch by asserting timing behavior and cleanup. Integration-test a SearchPanel by rendering the component with its dependencies and asserting visible results, loading states, and accessible interactions.

Performance rules that fit the style guide

Performance work becomes cleaner when the codebase already follows naming, structure, and purity rules.

High-impact standards include:

  • Code splitting with React.lazy() for routes or heavy secondary surfaces
  • React.memo for components that rerender unnecessarily and have stable props
  • Memoization of expensive derived values only when profiling shows the need
  • Bundle analysis during release work to spot oversized dependencies
  • Avoiding style and component recreation in render paths where identity churn hurts performance

Don't cargo-cult memoization. A style guide should push developers to protect expensive paths, not wrap everything reflexively.

Applying the guide in messy environments

Teams usually ask two cross-cutting questions.

How should a monorepo handle the React style guide?
Use one root baseline for linting, formatting, TypeScript settings, and accessibility rules. Then allow package-level additions only when a package has a real environment difference, such as a design system package versus an app shell.

How do you introduce the guide into a legacy codebase without freezing delivery?
Don't try to clean everything at once. Gate new and changed files first. Add autofixable formatting immediately. Add stricter lint rules in stages. Refactor by boundary, usually feature by feature or route by route.

The fastest way to fail a style-guide rollout is demanding perfection from untouched legacy files while product work continues.

That incremental approach keeps standards credible. Teams will adopt rules they can survive.

Frequently Asked Style Guide Questions

How should we structure the API data layer

Keep API code outside presentational components and close to the feature that owns it. A good default is a feature-local api/ folder with request functions, mapping helpers, and typed request or response models.

Don't let raw server payloads leak through the whole component tree. Normalize or map them near the boundary so UI components consume shapes that match UI needs. That makes refactoring easier when the backend changes and keeps components readable.

Should hooks be colocated with components or moved into a shared folder

Colocate by default.

A hook should live near the feature until at least two or more parts of the product need the same behavior and the abstraction is stable. Moving hooks into a global shared folder too early creates false reuse. It also makes ownership blurry, which weakens the style guide over time.

What's the best approach for a React monorepo

Use a shared baseline and local responsibility. The monorepo should centralize linting, formatting, TypeScript rules, token definitions, and core testing conventions.

Each package should still own its public API, local tests, and package-specific constraints. The style guide should define how packages expose components, hooks, and utilities so one package doesn't become a backdoor dependency on another package's internal files.

How do we apply a React style guide to an existing codebase without stalling roadmap work

Use a ratchet model.

Start with these actions:

  • Autofix formatting first: Prettier gives immediate consistency with low friction.
  • Enforce new-file standards: Require modern conventions for all new components, hooks, and tests.
  • Target change surfaces: When a team touches a feature, bring that file or folder up to the current guide.
  • Codify recurring review comments: If reviewers repeat the same feedback three times, it belongs in linting, templates, or the guide.

That last point matters more than is often understood. A living React style guide grows out of repeated engineering decisions. If the guide never changes, it's probably disconnected from how the product is built.

What should the style guide say about legacy class components

Don't spend energy writing polished standards for patterns you want to retire. Define a maintenance policy instead.

For example:

  • New work uses functional components and hooks.
  • Existing class components remain until touched for meaningful feature work or refactor opportunities.
  • Shared infrastructure should not add new dependencies on legacy patterns.

That keeps the standard pointed forward without turning migration into a separate project.


A React style guide earns its place when it changes behavior in the repo. Not when it reads well in a wiki.

If your team needs help turning these rules into an enforceable system, from component standards to accessibility workflows and scalable project architecture, Nerdify can help design and implement the engineering guardrails that keep React products maintainable as they grow.