react / react
React remains the component foundation, not the whole application plan
React gives teams a precise way to describe interfaces as components and keep the screen synchronized with changing data. Its small conceptual center has proved unusually durable, but the library intentionally leaves routing, data loading, deployment, and many production choices to frameworks and application owners.
WHAT TO KNOW FIRST
- React's durable value is its declarative component and state model, while most application architecture lives outside the core library.
- Effects are an escape hatch for synchronizing with external systems, not a general place for data flow or derived values.
- Current React includes server-oriented capabilities, but the framework determines how those capabilities are bundled, transported, cached, and deployed.
01A library with a deliberately narrow center
The official repository describes React as a JavaScript library for building user interfaces. That plain definition is more useful than treating it as a complete web platform. React owns the language developers use to express a tree of components, the rules for passing data into that tree, and the process that updates rendered output when state changes. It can be adopted inside one part of an existing page or serve as the component layer of a large application.
What React does not own is just as important. The current documentation says the library does not prescribe routing and data fetching, and it recommends starting a full application with a framework. Authentication, authorization, cache policy, database access, background work, asset delivery, and deployment remain application concerns. This separation lets React appear in many stacks, but it also means a team should evaluate the surrounding framework and runtime alongside the repository. Choosing React alone is a component decision, not a finished architecture.
02Components make interface ownership visible
A React component is a JavaScript function that returns a description of interface output. Components receive props, can hold state, and compose other components. The practical benefit is not merely reuse. A component gives one piece of interface an explicit input boundary and a place to keep the behavior that belongs to it. A search result, billing row, date picker, or entire route can be reasoned about in terms of data coming in, events going out, and rendered states in between.
Good boundaries are still a design task. Extracting every wrapper into its own component creates indirection without ownership, while leaving a whole screen in one function makes change risky. The strongest component boundaries follow product concepts or repeated interaction patterns. Props should describe what a child needs rather than expose a parent's entire state object. Keys in lists should be stable identities rather than array positions when order can change. React provides the composition mechanism, but a legible component tree comes from the domain language of the product.
03State should have one clear owner
State is information that changes over time and affects rendering. React's local state works well for an open menu, a draft input, or a selected tab. When two components must coordinate, the usual move is to lift the relevant state to their closest shared owner and pass values plus event callbacks down. Context can remove repetitive prop passing for values that truly apply across a subtree, such as theme or a stable service boundary, but it should not become a hidden global container for every changing value.
Many difficult React codebases store more state than the product actually has. A filtered list, formatted label, or boolean derived from existing values usually belongs in rendering, not in another state variable synchronized later. Reducers help when several events transform related state and the transition rules deserve names. External stores can be appropriate for data shared across distant areas, but they add their own subscription, serialization, and debugging model. Begin with the smallest owner and move state only when a concrete coordination problem appears.
04Hooks are rules for reusable behavior
Hooks let function components use state, context, refs, effects, and other React facilities. Their call-order rules are strict: Hooks run at the top level of components or custom Hooks, not inside conditional branches or ordinary functions. Those constraints allow React to associate each call with the right component state across renders. The official lint tooling can detect many violations, which makes the rules enforceable rather than a convention reviewers must remember by sight.
Custom Hooks are most useful when they package a coherent behavior, not when they hide a few lines for aesthetic reasons. A useOnlineStatus Hook can own a browser subscription and cleanup. A useInvoiceDraft Hook can expose domain actions around a reducer. The name signals that the function participates in React's lifecycle, and its returned interface should be as deliberate as any module API. Hooks share logic, not state instances, so each caller retains its own state unless the Hook connects to an external shared source.
05Effects are for systems outside React
The official learning material frames an Effect as a way to synchronize a component with an external system. Examples include connecting to a network service, subscribing to a browser API, or controlling a non-React widget. An Effect runs after React commits output and may return cleanup for the previous subscription or resource. Dependencies state which reactive values the synchronization uses. Omitting them or suppressing the linter can leave a callback reading stale values and make behavior depend on timing.
An Effect is usually the wrong tool for deriving display data, responding to a button click that already has an event handler, or copying props into state. Those patterns introduce an extra render and a second source of truth. Development Strict Mode may run setup and cleanup again to expose missing cleanup, which is a useful pressure test rather than a production bug. Before adding an Effect, ask which external system is being synchronized. If there is no concrete answer, ordinary rendering, an event handler, or a framework data API is probably clearer.
- Keep derived values in render unless the calculation is genuinely expensive and measured.
- Return cleanup for subscriptions, timers, observers, and connections created by an Effect.
- Treat dependency warnings as design feedback instead of silencing them by default.
06Server and client React need a framework contract
Modern React includes APIs and conventions used by frameworks for server rendering, streaming, Server Components, and Actions. These capabilities can keep data access near the server, reduce client code, and reveal useful interface states while work is still in progress. They are not a portable deployment recipe by themselves. A framework decides how modules are split, how server output reaches the browser, how navigation works, which values are cached, and where server functions execute.
That makes the server-client boundary an application security and performance boundary. Secrets and privileged checks belong on the server, but authorization still has to run at every protected operation. Values passed to client components must be serializable and safe to expose. Interactive components should be narrow enough that an entire page does not become browser code for one control. Teams comparing React frameworks should test caching, mutation failure, streaming behavior, and their deployment target instead of assuming the same React version makes every framework operationally equivalent.
07Testing should follow what the user can observe
React's component boundary makes isolated tests possible, but implementation-level assertions can become brittle quickly. A stronger test renders the component, finds elements the way a user or assistive technology would, performs an action, and checks the visible result. That approach covers the component's public behavior while allowing internal Hooks and helper functions to change.
Accessibility is part of the component contract. JSX makes it easy to produce semantic HTML, but it also makes div-based substitutes easy. Native buttons, labels, headings, and links carry behavior that custom elements must otherwise reproduce. Loading, empty, error, and disabled states deserve stories and tests alongside the happy path. Performance work should begin with profiling and bundle evidence, not reflexive memoization.
08When React is the right long-term dependency
React fits products where interactive state and reusable interface concepts justify a component system, and where the team values a large ecosystem plus broad hiring familiarity. It also supports gradual adoption, which matters when a complete rewrite would be reckless. A small React root can coexist with server-rendered pages until the product demonstrates where richer interaction earns its cost.
It is less persuasive for a mostly static information site that can ship clean HTML with minimal client code, or for a team seeking one opinionated tool to own the whole stack. React's flexibility creates recurring choices around frameworks, forms, data fetching, testing, and state. Those choices are manageable when recorded and periodically simplified. The best React codebases do not showcase every ecosystem pattern. They use the library's small center consistently and let product boundaries, not fashion, determine the rest.
A SENSIBLE FIRST HOUR
Start small enough to learn the repo
- Work through the official Quick Start and build one small component tree using props, local state, conditional rendering, and a keyed list.
- Choose an officially recommended framework for a new production application, or document why a build-tool-only setup is sufficient for your use case.
- Add the React Developer Tools, enable the repository's recommended lint rules, and remove any Effect that merely derives one value from another.
- Build and test a production bundle, then inspect client JavaScript, accessibility behavior, error states, and data freshness on the actual route.
SOURCE LEDGER
What this review is built on
We use the project repository and first-party documentation. Access, licenses and project direction can change, so recheck the linked source before making a production decision.