Skip to content

Frontend

React Development Company

Component-driven user interfaces, built by engineers who own the architectural decisions React deliberately leaves open to you.

Overview

React is a JavaScript library for building user interfaces out of components: self-contained pieces of UI that describe what the screen should look like for a given state, and let React work out how to update the DOM efficiently. It is deliberately not a full framework. React gives you the view layer and a disciplined mental model, and it gives you almost nothing else. No router. No data-fetching layer. No build setup. No opinion on how to organise a codebase of four hundred files. That restraint is a strength when you want control over those decisions, and a liability when you wanted the tool to make them for you.

The core idea is declarative rendering. You describe the interface as a function of state, and when state changes React re-renders the affected components into a lightweight tree, diffs it against the previous one, and applies the minimum set of real DOM operations through a process called reconciliation. In practice this means you stop hand-writing imperative DOM updates, stop tracking which element needs which class removed, and start reasoning about data flowing one way through a tree. Once a team genuinely internalises unidirectional data flow and hooks, React code becomes predictable to read and, more importantly, predictable to change.

React has become the default choice for interactive web front ends, and that ubiquity is a real engineering asset: a deep hiring pool, a library for almost every requirement, and battle-tested patterns for problems your team is not the first to hit. The same ecosystem churns hard. Libraries that were consensus three years ago are unmaintained today, and the community’s recommended way of doing a thing shifts every couple of years. We treat that churn as a cost to be managed rather than a fashion to be followed, and we make conservative, defensible library choices you will not resent in eighteen months when someone else is maintaining them.

What we actually build with it: operational dashboards and data-dense internal tools, in-browser editors and configurators, customer portals behind a login, embedded widgets that have to live politely inside somebody else’s page, and design systems that several product teams consume. We also do a fair amount of rescue work on React codebases that grew faster than their conventions did. And we will say plainly when React is the wrong answer: if your product is a content site that needs to rank, the honest recommendation is a framework with server rendering, not a client-rendered React app with search-engine workarounds bolted on afterwards.

Best for: Interactive, state-heavy web applications where a component model pays for itself, and where a senior team owns the architectural decisions React deliberately leaves open.

Why teams choose React

  • Predictable UI derived from state

    You describe what the screen should look like for a given set of data and let reconciliation work out the DOM operations. This removes an entire category of defect: the half-updated interface, the stale label, the modal that thinks it is closed while its backdrop disagrees. Complex screens become tractable because there is exactly one place to look when something on screen is wrong, and that is the state that produced it.

  • Component boundaries that let a team work in parallel

    Well-drawn boundaries let several engineers build different parts of a product at once without treading on each other, and let you reuse UI rather than re-implement it in three places with three subtly different behaviours. Boundaries are the difference between a codebase that ages gracefully and one that calcifies into files nobody wants to open.

  • One skillset across web and mobile

    React Native shares React’s model, so investment in React patterns, state handling and even domain logic carries across to native iOS and Android. If you own both surfaces, that is a genuine saving in hiring, review and onboarding, provided you go in understanding that the visual layer is not shared.

  • A hiring pool and an exit route

    Whatever we build in React, you can staff. That matters more than teams expect at commissioning time and enormously at handover time. Choosing a niche framework buys elegance and costs you the ability to replace the people who understand it.

Why businesses choose React

  • You want an interactive front end that stays maintainable as features accumulate and as people join and leave the team, rather than one that is pleasant for six months and then feared.
  • You value a deep talent pool and a mature ecosystem over the elegance of a smaller, more opinionated framework, because you intend to own this codebase for years.
  • You are building for web and mobile and want a single engineering approach, a single review culture and a single set of conventions across both.
  • You need a design system that several teams consume, and you want the composition model that makes flexible components possible without a configuration explosion.
  • You have, or want us to supply, the senior judgement to make React’s open architectural decisions well and once, up front, before there is enough code that changing them becomes a project of its own.

What we build with React

The capabilities this technology is genuinely strong at, and what we most often build with it.

  • Function components and hooks

    Modern React is written as function components with hooks: useState and useReducer for local state, useEffect for genuine synchronisation with the outside world, useMemo and useCallback for referential stability, and custom hooks to package reusable behaviour. We write them idiomatically and we know where they bite. Most effects we encounter in inherited codebases should not exist: they are computing derived values that could be calculated during render, or synchronising two pieces of state that should have been one.

  • Reconciliation, keys and the render cycle

    React renders a component tree, diffs it against the previous tree, and applies the smallest set of DOM changes. Understanding that cycle is what separates engineers who can fix a sluggish interface from those who scatter memoisation and hope. Keys in particular are not a lint requirement to be satisfied with an array index: they tell React which item is which across renders, and getting them wrong causes input state to jump between rows in ways that look like ghosts in the machine.

  • Unidirectional data flow

    Data flows down through props and change flows back up through callbacks. This one-way discipline is what makes a large tree debuggable, because any wrong pixel can be traced upward to the state that produced it. We lift state to the lowest common ancestor that needs it and no higher, which keeps re-render scope tight and keeps components reusable in contexts their author did not anticipate.

  • The state management decision, made deliberately

    React ships local state and nothing else, so the shared-state choice is yours. We separate it by kind. Server state, meaning data that lives in your API and is merely cached in the browser, goes to a query library that handles caching, revalidation, retry and de-duplication. Genuine client state, meaning things the server has never heard of like a half-open panel or a multi-select selection, goes in a small store such as Zustand, or Redux Toolkit where the team already knows it. URL state goes in the URL, where it is shareable and survives a refresh. Context is reserved for low-frequency values such as theme or current user, because a Context that changes often re-renders everything beneath it.

  • Composition, headless behaviour and design systems

    React favours composing small components and hooks over configuring large ones. We use that to build design-system components that stay flexible without accumulating a prop for every possible variation: behaviour and accessibility live in a headless hook or an unstyled primitive, and presentation composes on top. It is the difference between a Button with nine boolean props and a set of components that assemble into whatever the design actually needs.

  • Concurrent rendering and transitions

    Modern React can interrupt, prioritise and abandon rendering work. Marking a state update as a transition lets an urgent update such as typing stay responsive while an expensive one such as filtering ten thousand rows renders in the background, and useDeferredValue does the same for derived views. Suspense lets a slow subtree show a fallback without the parent orchestrating loading flags by hand. We use these where they measurably help an interaction, not as decoration.

  • Actions, optimistic updates and form handling

    Recent React gives form submission and mutation a first-class shape: an action function, pending state without a hand-rolled boolean, and optimistic updates that show the intended result immediately and reconcile when the server answers. Combined with a serious form library for validation and field arrays, this removes most of the tedious, bug-prone plumbing that used to surround every non-trivial form.

  • Accessibility as engineering, not audit

    We build with real semantic elements, managed focus on dialogs and route changes, keyboard support for every interaction that has a mouse equivalent, and ARIA only where native semantics genuinely fall short. Doing this during the build costs a fraction of what a remediation project costs after a procurement questionnaire or a complaint has forced the issue.

  • Testing that survives refactoring

    We test components through the interface a user actually meets: rendered output, roles, labels and interaction, rather than internal state and implementation details. Tests written that way keep passing when you restructure the component and keep failing when you break the behaviour, which is the only way test suites stay trusted rather than routinely skipped.

Use cases

  • Operational dashboards and internal tools

    Data-dense interfaces with live updates, filtering, sorting, drill-down and bulk actions. This is React at its most convincing: state is complicated, interactions are constant, SEO is irrelevant, and the users are professionals who will use the tool all day and notice every stutter.

  • In-browser editors, builders and configurators

    Form builders, document and diagram editors, product configurators, pricing tools and design surfaces where interaction state is intricate, undo and redo are expected, and every action must feel immediate. These products live or die on render performance and state modelling, both of which are React strengths when the architecture is right.

  • Customer portals and account areas

    Booking flows, subscription management, claims journeys and multi-step onboarding behind a login. Search visibility does not apply, the interaction is rich, and the value is in getting complicated flows to feel simple.

  • Design systems and shared component libraries

    A versioned library of accessible, composable components consumed by several product teams, with documented props, sensible defaults and behaviour that is identical everywhere. The engineering challenge is API design rather than pixels, and it is the work that pays back longest.

  • Embedded widgets and third-party UI

    Interfaces that must run inside a customer’s page without leaking styles, conflicting with their scripts or bloating their page weight. Bundle discipline and style isolation dominate the design, and React is workable here provided somebody is watching the payload closely.

  • Shared web and mobile products

    Products that exist as a web application and a React Native app, where one team reuses domain logic, validation, API clients and conventions across both while writing the screens separately for each platform.

  • Rescuing a sprawling React codebase

    An application that started small, changed hands twice and now has three data-fetching approaches, a Redux store full of cached server data and a components folder nobody can navigate. We assess it, agree the target architecture, and refactor toward it incrementally while the team keeps shipping, rather than proposing the rewrite everyone secretly wants and nobody can afford.

When React is the right choice

  • Right when the interface is genuinely interactive: dashboards, editors, configurators, real-time tools, long multi-step flows. Where UI state is intricate and changes constantly, React’s component model and reconciliation earn their complexity many times over. This is its home ground and nothing else in the ecosystem does it better with as little risk.
  • Right when you want to share engineering patterns and people between web and mobile. React and React Native share the component model, hooks and most non-visual logic, so a team can move between the two surfaces without relearning how to think. You will not share the UI itself, but you will share the parts that take longest to get right.
  • Right when you are building a component library or design system that multiple teams will consume. React’s composition model, with children, render props and headless behaviour hooks, is unusually good at expressing a component that is flexible without turning into a thirty-prop configuration object.
  • Right when hiring and handover matter. The talent pool is the deepest in front-end development, which means the codebase you commission is one your own team, or your next agency, can realistically pick up. That is a strategic property, not a technical one, and it is often the deciding argument.
  • Wrong for a mostly static content site: marketing pages, a blog, brochureware, documentation. Plain HTML with a sprinkle of JavaScript, or a static site generator, will load faster on a poor connection, cost less to build, and be far simpler to maintain in three years. Reaching for React here is a decision you make for the CV, not for the user.
  • Wrong for public pages that must be indexable and fast on first load. React on its own renders in the browser, so a crawler and a first-time visitor both receive an empty shell until JavaScript downloads and executes. That is a framework problem, and the answer is Next.js, not more client-side cleverness inside a bare React app.
  • Wrong for teams who want the tool to decide. React leaves routing, data fetching, state management, folder structure, styling and build tooling entirely to you. If nobody on the project owns those decisions with authority, the codebase sprawls into five different ways of doing the same thing. If that is your situation, take an opinionated framework instead and accept its opinions gladly.

React: pros and cons

Strengths

  • The largest ecosystem and community in front-end development. For almost any requirement, a mature library, an established pattern or a well-argued answer already exists, and the hiring pool is deep enough that staffing is rarely the constraint.
  • Declarative, component-based code is easier to reason about, review and test than imperative DOM manipulation, once the model clicks for the team.
  • Reconciliation gives good interactive performance for most applications with no hand-tuning, and the tooling to diagnose the exceptions is excellent.
  • Skills, patterns and non-visual logic transfer directly to React Native, so one team can credibly serve web and mobile.
  • It is unopinionated enough to fit almost any backend, any styling approach and any build pipeline, which makes it a safe choice inside an existing estate rather than a rewrite trigger.
  • Backed by a large engineering organisation with a long track record of careful, backwards-compatible evolution. Upgrades have historically been survivable, which is not true of every front-end tool.

Trade-offs

  • It is not a framework, and pretending otherwise is how projects go wrong. You must choose, assemble and then maintain routing, data fetching, forms, state management and build tooling yourself. Each of those is a decision with a wrong answer, and the wrong answers are discovered late.
  • State management is the single most expensive decision on a React project and the ecosystem has changed its mind about it repeatedly: Flux, then Redux everywhere, then Context for everything, then Redux Toolkit, then lightweight stores, then the realisation that most of what teams were storing was server data that never belonged in a client store at all. Choosing wrong is not a small mistake. Putting server data in Redux, for example, means hand-writing caching, invalidation and de-duplication that a query library gives you free, and unpicking it later touches every component that reads it.
  • Client-only rendering is bad for search visibility and slow to first meaningful paint, particularly on mid-range phones and poor networks. No amount of bundle tuning fully removes the cost of shipping an application to build a page that could have arrived as HTML.
  • The ecosystem churns. Libraries are abandoned, recommended patterns rotate, and a codebase written to the best advice of its era looks dated surprisingly fast. Keeping current is an ongoing budget line, and the alternative is a dependency tree you cannot safely upgrade.
  • Hooks have sharp edges that catch experienced engineers, not just beginners: stale closures, dependency arrays that lie, effects used to synchronise state that should have been derived, and cascading re-renders from a Context that changes too often. These bugs are subtle, intermittent and expensive to diagnose.
  • Flexibility invites sprawl. Without conventions that someone enforces, a large React codebase drifts into several competing styles of component, three ways to fetch data and a folder structure that made sense to whoever was on the project in month four.
  • Accessibility is not free. React will happily render a div that behaves like a button and looks fine, and nothing in the library will stop you. Keyboard behaviour, focus management and screen-reader semantics are engineering work you either budget for or ship without.
  • Major-version ecosystem lag is real. When React ships a significant release, the surrounding libraries take time to catch up, so being early on a new version can mean living with peer-dependency warnings and patched forks. We usually wait.

Architecture

Because React makes so few decisions for you, architecture is where a project is won or lost, and it is won in the first fortnight. We settle the load-bearing choices before code volume makes them expensive: how modules are grouped by feature rather than by technical type, where the boundary sits between presentational components and the ones that hold state, how data is fetched and cached, how styling works, and which state is local, which is genuinely shared client state, and which is server state that should never have been copied into a store at all.

That last distinction removes most of the complexity teams associate with React. Server state is data that belongs to your API. The browser holds a cache of it, and caches need freshness rules, invalidation, retry and request de-duplication, which a query library provides and which teams otherwise rebuild by hand, badly, across dozens of components. Genuine client state is then small, explicit and easy to reason about. We push as much as we can into the URL, because state in the URL is shareable, bookmarkable and survives a reload for free, which is a user-facing feature disguised as an architectural choice.

Component structure follows a simple rule: components that fetch and decide are separate from components that render. That keeps the rendering layer easy to test, easy to reuse and easy to move into a design system later. We keep prop interfaces narrow and typed, avoid passing whole objects where two fields will do, and resist the temptation to make one component handle every variant a designer has ever drawn. When a component grows a fourth boolean prop, that is usually the signal to split it or to expose composition instead.

Above the component tree sits the question React does not answer: routing and rendering. For an application behind a login, a client-side router is perfectly adequate and adds no server complexity. For anything public, indexable or performance-critical on first load, that is the point at which we stop bolting server rendering onto a bare React app and move to a framework built for it. Deciding this early matters, because a React codebase with clean boundaries can adopt server rendering without tearing up the component tree, and one without them cannot.

Performance

React is fast enough by default for most applications, and its performance problems are boringly predictable: too many components re-rendering on every keystroke, too much JavaScript downloaded before anything appears, and expensive work done during render that should have been done once or not at all. We diagnose with the profiler rather than by intuition, because the component that feels slow is very often not the one doing the work.

The fixes are ordinary engineering. Keep state as low in the tree as possible so an update touches a small subtree. Split a frequently-changing Context so a value that updates every second does not re-render consumers that only care about the user’s name. Memoise where the profiler shows it helps, and delete memoisation that exists only because someone was nervous, since every memo has a cost of its own and a dependency array that can quietly go wrong. Virtualise long lists so the browser renders the visible rows rather than all ten thousand. Debounce or defer expensive derived work. Where the React Compiler is a fit for the codebase, it removes much of the manual memoisation entirely, and we treat that as a simplification to adopt when it is stable for the stack in front of us, not a novelty to chase.

The largest wins, though, are usually about how much JavaScript ships and when. We treat the bundle as a budget with a number on it, split by route, lazy-load the heavy pieces such as charting libraries, rich text editors and date pickers so they arrive when the screen that needs them does, and audit dependencies for the ones that quietly weigh more than the feature they provide. We are also honest about the ceiling: a client-rendered application pays a first-load cost that tuning reduces but never eliminates. If that cost matters to your users or your search ranking, server rendering is the answer, and no amount of clever client-side work substitutes for it.

Security

React escapes rendered values by default, which closes off most cross-site scripting without anyone thinking about it. The notable hole is dangerouslySetInnerHTML, which is named that way for a reason. We avoid it, and where rendering user or CMS-authored HTML is genuinely unavoidable we sanitise with a maintained library on a strict allowlist, on the server where possible, and treat the result as a deliberate, reviewed exception rather than a convenience. The same caution applies to anything that ends up in an href, a style attribute or a dynamically injected script tag.

The larger front-end truth is that nothing running in a browser can be trusted, and that includes your own code. Authorisation is enforced on the server for every request, never merely by hiding a button; a hidden button is a UX choice, not a control. Secrets do not live in front-end code, because a bundle is a public document and anyone can read it. Tokens are stored with a deliberate decision about the trade-off between httpOnly cookies with CSRF protection and browser storage with its XSS exposure, made once and documented, not inherited unexamined from whatever starter template the project began with.

Dependencies are the part people underestimate. A React application with a rich ecosystem behind it can pull in hundreds of transitive packages, each one code you did not write and will not read, executing in your users’ browsers with full access to the page. We keep the tree deliberately small, prefer well-maintained libraries with narrow scope over convenience bundles, lock versions, run vulnerability scanning in the pipeline, and are sceptical of any package that wants to run install scripts. We are equally careful with third-party tags: analytics, chat widgets and tag managers all execute with the same privileges as your application, and a content security policy that actually constrains them is worth the afternoon it takes to get right.

Scalability

A React front end scales with the team and the codebase far more than with traffic. Request load is carried by your servers and your data layer; React’s scaling problem is staying coherent as features multiply and as the people who made the original decisions move on. That is an organisational problem with technical levers, and the levers are well understood.

Feature-based structure keeps related code together so a change lands in one place rather than five. A shared component library stops each team inventing its own modal. Clear state ownership prevents two features fighting over the same slice of data. Typed contracts, in TypeScript, mean a change to a shared shape produces a compile error rather than a silent runtime surprise in a part of the product nobody was thinking about. Lint rules and code review carry the conventions that documentation alone never sustains, because rules that are not enforced are suggestions.

We also plan for the rendering demands changing, because they usually do. A product that started as an internal tool acquires a public marketing surface; a dashboard acquires a shareable report page that has to load fast for someone who has never visited before. A React application with clean boundaries between UI, data access and routing can adopt server rendering or move parts to a framework incrementally. One where components fetch their own data through a tangle of effects, and where routing assumptions are scattered through the tree, cannot, and that is how teams end up facing a rewrite they never budgeted for.

React integrations & ecosystem

The technologies we most often pair with it. Each links to how we work with it.

How we work

We start by closing the decisions React leaves open, because they are cheap now and expensive later: folder structure, the state taxonomy, the data-fetching approach, the styling strategy, the component library or the decision to build one, the routing model, and the testing approach. We write them down in a short document that fits on two pages and that a new engineer can read on their first morning. This is not ceremony. It is the difference between one codebase and four codebases sharing a repository.

Then we build in thin vertical slices. One real feature, end to end, deployed, rather than a scaffold that looks impressive and does nothing. A vertical slice tests the architecture against reality: it exposes the awkward loading state, the error case nobody drew, and the shape of API response that does not fit the model. Finding those in week two is cheap. Finding them in month four, after twenty screens were built on the same assumptions, is not.

Throughout, accessibility and performance are build-time concerns rather than a pre-launch panic. Keyboard behaviour and focus management are part of a component being finished. Bundle size is watched as it grows, because bundles grow through a hundred small additions and nobody notices until the number is embarrassing. Tests target behaviour, not implementation, so they survive the refactors we expect rather than obstructing them.

The engineers who design the front end are the ones who write it and keep it running afterwards. That is what we mean by operating what we build: decisions get made by people who will live with them, which reliably produces more boring choices than a team optimising for the pitch. You end up with a typed codebase, a documented set of conventions, and a front end your own team can pick up and extend without ringing us first.

The service behind it

Delivered throughCustom Software Development

What we build with React

The disciplines this technology most often shows up in, from a first build to taking over and stabilising an existing one.

How we deliver

  1. 01

    Discover

    We map the system, the constraints and the business it serves, including the parts nobody documented.

    Architecture brief

  2. 02

    Architect

    Decisions get made, written down and defended before a line of production code exists.

    Decision records

  3. 03

    Build

    Short cycles against working software. You see progress in the product, not in a status deck.

    Shipping increments

  4. 04

    Operate

    Monitoring, incident response and iteration. The system is alive, so the engagement is too.

    Runbooks & SLOs

Weighing up React?

A short call with engineers who build in it and operate the result. If React is the wrong tool for what you are doing, we would rather tell you now than bill you later.

Industries we use React in

Domain knowledge changes what gets built. A few of the sectors we know before the first meeting.

Also in Frontend

Why teams choose us for React

  • Senior engineers only

    React rewards experience and punishes guesswork, because its hardest problems are architectural rather than syntactic. The people making your decisions have made them before, on codebases they then had to maintain. There are no juniors learning the state management lesson on your budget.

  • We operate what we build

    We run the systems we ship, so we optimise for the eighteen-month maintenance reality rather than the launch demo. In practice that means conservative library choices, small dependency trees, and code your own team can read without a tour guide.

  • Opinionated where it counts

    React’s flexibility needs someone to impose order on it. We bring a considered default position on structure, state and data fetching, we explain why, and we adapt it to your context rather than applying a template. The alternative, which we see often in inherited codebases, is a project where every engineer answered the same question differently.

  • Honest about when not to use React

    If a static site generator, plain HTML, or a server-rendered framework would serve you better, we will say so before you spend money. We would rather lose the project than build you something you did not need and then charge you to maintain it.

Typical timeline

  1. 01

    Discovery and architecture

    One to two weeks agreeing the interactions, the data flow, the state taxonomy, the library choices and the rendering approach, and writing them down. The foundations are settled while changing them is still cheap.

  2. 02

    First vertical slice

    Two to three weeks delivering one real feature end to end, deployed and usable, so the architecture is proved against actual data, actual errors and actual latency rather than against a plan.

  3. 03

    Iterative build

    Feature-by-feature delivery in short cycles, each one shippable, with accessibility and bundle size checked as we go. You see working software continuously rather than a demo at the end.

  4. 04

    Hardening

    Profiling the interactions that matter, tightening the bundle, covering the load-bearing paths with tests that target behaviour, and closing the accessibility gaps found in review.

  5. 05

    Handover and support

    Documented conventions, a readable component API surface, and a walkthrough for your team. Then whatever ongoing arrangement suits you, from occasional review to continued senior engagement.

How pricing works

  • Most engagements open with a short paid discovery: we map the screens, the interactions, the data behind them and the constraints you are actually under, and come back with an architecture and an estimate grounded in your product rather than an average. It is deliberately small and it is chargeable, because the thinking is the valuable part and free estimates are guesses dressed up.
  • Fixed-scope builds suit a well-defined front end: a specific dashboard, a customer portal, a component library, a defined set of flows. We quote once the scope is genuinely understood, which is what discovery is for. Where the requirement is inherently open, we say so rather than quoting a number we will have to renegotiate.
  • Monthly senior engagement suits ongoing product work where scope evolves week to week and you want continuity and accumulated context rather than a fixed deliverable. You get named senior engineers, a predictable cost, and the same people who built the thing continuing to build it.
  • Focused audits and rescues are priced by the assessment: a performance investigation, an architectural review, an accessibility audit, or diagnosing why a React project has stalled. These are usually short, and they often end with an honest recommendation to fix rather than rebuild.
  • Third-party costs are yours and unmarked-up. Hosting, CDN, error tracking, analytics, and any commercial component licences such as a data grid or charting library are billed to your own accounts at the price the vendor charges. We recommend what the product needs, you own the contracts, and we take no margin on anyone else’s software.

Hire React engineers

Need React capacity on your own team? We embed named senior engineers into your existing team (reporting to your leads, working in your rituals), so you add capacity without a hiring cycle.

Hire React engineers

Common questions

Is React a framework?

No, and the distinction has real consequences. React is a UI library: it handles the view layer and a data-flow model, and it does not provide routing, data fetching, forms or a build setup. You assemble those yourself, or you adopt a framework such as Next.js that supplies them on top of React. Choosing React means accepting ownership of decisions a framework would otherwise make for you, which is fine if someone senior is making them and a problem if nobody is.

Is React good for SEO?

Not on its own. A plain React application ships an essentially empty HTML document and builds the page in the browser, so a crawler, a social preview and a first-time visitor on a slow phone all get nothing until the JavaScript arrives and executes. If public, indexable pages matter to your business, we use a framework that renders on the server. For an application behind a login, where nothing should be indexed anyway, client rendering is usually the simpler and perfectly correct choice.

Should we use React for a simple website?

Usually not, and we will tell you so. For a marketing site, a blog or brochureware, plain HTML or a static site generator will be faster for your visitors, cheaper to build and far simpler to hand to whoever maintains it next. React earns its complexity when the interface is genuinely interactive and state-heavy. If your project falls on the wrong side of that line, using React is a cost with no matching benefit.

Redux, Context, or something else for state?

It depends entirely on what kind of state it is, and most teams that struggle here are struggling because they never made that distinction. Data that lives in your API is server state, and it belongs in a query library that handles caching, revalidation and de-duplication rather than in a store you maintain by hand. State that belongs in the address bar, such as filters and the current tab, belongs in the URL. Context is right for low-frequency global values like theme or current user, and wrong for anything that changes often, because it re-renders everything beneath it. What is left is genuine client state, and it is usually small enough that a lightweight store handles it comfortably. We choose per project, not by habit.

How do you keep a large React codebase from turning into a mess?

With conventions that are decided early, written down, and then enforced by tooling rather than by hope. Feature-based structure so related code lives together, a clear separation between components that fetch and components that render, one agreed way to fetch data, TypeScript so shared shapes are checked rather than assumed, and lint rules plus code review carrying the rest. None of it is clever. The mess we get called in to fix is almost never caused by a lack of talent; it is caused by nobody having authority over these decisions while the codebase tripled in size.

Can we share code between our React web app and a React Native mobile app?

Partly, and usefully, though less than the marketing suggests. React Native shares the component model, hooks and mental model, so patterns, skills, domain logic, validation rules and API clients transfer directly and one team can credibly own both. The UI itself does not transfer, because native components are not DOM elements and the platform conventions genuinely differ. Plan to share the logic and the people, and to write the screens twice.

We have an existing React app that has become slow and hard to change. Can you fix it rather than rebuild it?

Usually yes, and that is normally the right call. We start with an assessment: profile the interactions that actually feel slow, look at what the bundle contains, and map how state and data fetching are organised. Slowness is generally a small number of specific causes, most often unnecessary re-renders, an oversized bundle and unvirtualised lists, rather than something diffuse. Hard-to-change is generally a structural problem that can be refactored toward a target architecture incrementally while you keep shipping. A rewrite is the last resort, because it stops delivery for months and tends to recreate the original problems with newer libraries.

Which React version and libraries would you choose for a new project today?

The current stable React release, and a deliberately small set of libraries around it: a router, a query library for server state, a form library, a styling approach the team can live with, and as little else as we can manage. We are conservative here on purpose. Every dependency is code we did not write, an upgrade obligation and a potential abandonment risk. We would rather write fifty lines ourselves than take a package that solves it in five and then goes unmaintained for two years.

Building on React?

Tell us what you are building and where it is stuck. A senior engineer reads it and gives you an honest read on whether React is the right fit for the problem, or what we would reach for instead.

  1. 01A senior engineer reads it. Not a form queue, and not an account manager.
  2. 02We reply either with questions or with a straight answer that we are not the right fit.
  3. 03If it looks like a fit, a technical call with the person who would actually run the delivery.
  4. 04Then scope, effort and risk in writing, before anyone signs anything.

Two fields required. We reply to real enquiries. No list, no sequence.