React Advanced: Performance, Patterns and Production
TypeScript, Accessibility and Shipping
In this lesson you will
- Type props, state and events with TypeScript
- Apply core accessibility practices in React
- Use error boundaries and Suspense, and prepare a production build
Introduction
Professional React apps are typed, usable by everyone and prepared for failure. This final lesson brings those together, plus the steps to ship.
TypeScript with React
TypeScript catches mistakes before you run the code. Describe props with a type:
React (TSX)
import { useState } from "react";
type ButtonProps = {
label: string;
onClick: () => void;
variant?: "primary" | "secondary";
};
function Button({ label, onClick, variant = "primary" }: ButtonProps) {
return <button className={variant} onClick={onClick}>{label}</button>;
}
function Counter() {
const [count, setCount] = useState<number>(0);
return <Button label={`Clicked ${count}`} onClick={() => setCount(count + 1)} />;
}- A union type such as
"primary" | "secondary"limits values to valid choices. useState<number>states the type of state, useful when the starting value does not show it, for exampleuseState<User | null>(null).- Events are typed:
React.ChangeEvent<HTMLInputElement>for an input's change event. - Define the shape of API data as types, and validate it at runtime where the data comes from outside.
Quick quiz
What does the type 'primary' | 'secondary' on a prop allow?
Accessibility
Accessibility (often abbreviated a11y) means people with disabilities, using screen readers, keyboards, magnification or voice control, can use your app. It also helps everyone with poor lighting, a broken mouse or a small screen.
Core practices:
- Use semantic HTML:
buttonfor actions,afor links, headings in order,labelfor inputs. A clickabledivdoes not work for keyboard users unless you rebuild everything a button gives. - Keyboard support: everything must work with Tab, Enter and Space, with a visible focus style.
- Text alternatives:
alttext for meaningful images, and emptyalt=""for decorative ones. - Colour contrast that is high enough, and never colour as the only signal.
- ARIA attributes only to fill gaps that semantic HTML cannot, such as
aria-expandedon a menu button. The first rule of ARIA is not to use ARIA if a native element does the job. - Manage focus when content changes, for example moving focus into a dialog and back when it closes.
- Announce updates with live regions such as
role="status"for messages that appear. - Test with the keyboard alone, a screen reader and automated tools such as the axe browser extension and the ESLint jsx-a11y plugin.
Error boundaries
An error while rendering can blank the whole page. An error boundary catches errors in its children and shows a fallback instead:
React (JSX)
import { Component } from "react";
class ErrorBoundary extends Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error(error, info); // send to a logging service in production
}
render() {
return this.state.hasError ? <p>Something went wrong.</p> : this.props.children;
}
}Wrap risky sections, and log the errors. Libraries such as react-error-boundary provide a ready-made version. Boundaries do not catch errors in event handlers or async code, so handle those yourself.
Suspense and lazy loading
Suspense shows a fallback while a part of the tree is waiting, for example for lazily loaded code:
React (JSX)
import { lazy, Suspense } from "react";
const Settings = lazy(() => import("./Settings"));
function App() {
return (
<Suspense fallback={<p>Loading...</p>}>
<Settings />
</Suspense>
);
}Preparing for production
- Build the optimised bundle with your tool (Vite, Next.js and so on), and check its size.
- Environment variables: only public values go in front-end code. Secrets belong on a server.
- Error and performance monitoring in production, so you hear about problems before users complain.
- Security: keep dependencies updated, avoid inserting raw HTML, and use HTTPS and security headers.
- SEO and sharing: titles, descriptions and server rendering where needed.
- Automate: tests, type checks and linting in continuous integration, then deploy from the pipeline.
- Document: a README that explains how to run, test and deploy.
Where to go from here
- Learn a framework such as Next.js for routing, server rendering and data loading. This very website is built with it.
- Practise by building real projects, and read other people's code.
- Keep up with the official React documentation as it evolves.
Try it yourself
Convert one of your components to TypeScript with typed props. Then run it with the keyboard only, add an error boundary around it, and check it with an accessibility tool.
Summary
- TypeScript types props, state and events, and catches mistakes early.
- Accessibility starts with semantic HTML, keyboard support, labels, contrast and focus management.
- Use error boundaries and Suspense for resilience, and automate tests, monitoring and deployment before shipping.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading