Coding Standards

React Coding Standards

Foundational

The full reference for building React UIs at Finperiti: components, props, state, effects, hooks, data fetching, performance, forms, context, accessibility, and security. A few clear habits keep React working well: immutable state, correct effect dependencies, and composition. Without them you get stale data, infinite loops, and leaks. We write React in TypeScript; follow TypeScript Coding Standards and Gotchas: React alongside this.

We build function components with hooks, in strict TypeScript. Most React bugs come from misunderstanding rendering and state, so these standards cover the safe patterns in depth. Accessibility and security are part of the standard, not extras. The UI runs in a hostile browser and must work for everyone.

ESLint (including the rules-of-hooks and exhaustive-deps plugins) and Prettier enforce much of this. This page is the shared understanding and the conventions tools cannot enforce.

Components & composition

Props & contracts

State & immutability

Mutating state in place items.push(newItem); // mutates the same array
setItems(items); // same reference, so React may not re-render

React compares references to decide what to re-render. The array is the same object, so the change can be missed.

Creating a new array setItems([...items, newItem]); // a new array reference

A new reference tells React the state changed, so it re-renders reliably.

Effects & lifecycle

Mutation, bad effect, index key useEffect(() => { setRows(rows); }); // no deps, so it loops
rows.push(newRow); // mutates state
{rows.map((r, i) => <Row key={i} ... />)} // index key

An effect with no dependency array runs on every render and loops. Mutating rows is not detected and can corrupt state. Index keys link the wrong rows when the list changes. Three classic React bugs.

Immutable, scoped effect, stable key useEffect(() => { const sub = api.subscribe(onMsg); return () => sub.close(); }, [api]);
setRows(prev => [...prev, newRow]); // new array
{rows.map(r => <Row key={r.id} ... />)} // stable id key

The effect synchronises with an external source and cleans up, state updates immutably with the functional form, and rows are keyed by a stable id.

Hooks rules & custom hooks

Data fetching

Performance

Inline prop defeats memoisation save()} />

The object and function literals are new on every render, so the memoised child sees changed props and re-renders every time.

Stable references const style = useMemo(() => ({ margin: 8 }), []);
const onClick = useCallback(() => save(), [save]);

The references stay the same between renders, so the memoised child only re-renders when its props really change.

Context & shared state

Forms, accessibility & security

XSS via innerHTML

If userBio contains <script> or an onerror handler, it runs in the victim's session. This is a classic stored XSS. Render it as text, or sanitise it with a trusted library first.

Let React escape it
{userBio}
// React escapes the content automatically

JSX text rendering escapes HTML. The bio shows as plain text, and no injected markup runs.

Self-review checklist

Why it matters: React is simple once you understand it and bug-prone when you do not. These components are how customers see a financial product, so they must be fast, accessible, and secure. Deep, consistent standards for components, state, and effects, plus built-in accessibility and security, keep the UI reliable and inclusive as the team and app grow.