React inside Aurelia

Libception. Learn how to use React inside of your Aurelia applications.

Aurelia's design embraces flexibility and interoperability, making it well-suited for integration with other libraries and frameworks. One common scenario is incorporating React components into an Aurelia application. This integration showcases Aurelia's adaptability and how it can leverage the strengths of other ecosystems. Below, we provide a detailed guide and code examples to integrate a React component seamlessly into an Aurelia 2 application.

Install Dependencies

First, ensure that your Aurelia project has the necessary dependencies to use React. You'll need React and ReactDOM, plus the matching type packages when you compile with TypeScript.

npm install react react-dom
npm install --save-dev @types/react @types/react-dom

Keep the @types versions in sync with the React major you're using (for example, @types/react@19 with react@19). If you're validating a future React release candidate, follow the React upgrade guide instructions to alias the preview types-react packages so your compiler picks up the experimental definitions.

Create a React Component

For this example, let's create a simple React component. You can replace this with any React component you need.

// src/components/my-react-component.tsx
import type { FC } from 'react';

export interface MyReactComponentProps {
  message?: string;
}

export const MyReactComponent: FC<MyReactComponentProps> = ({ message = 'Hello from React!' }) => (
  <div>{message}</div>
);

export default MyReactComponent;

Create an Aurelia Wrapper Component

To integrate the React component into Aurelia, create a wrapper Aurelia component that will render the React component.

This wrapper exposes the React component and its props as bindables. It uses React's createRoot API—the modern entry point for React 18 and React 19 apps—to render the component inside Aurelia's DOM container. The wrapper handles the full React lifecycle by creating the root in attached(), re-rendering in response to Aurelia bindable updates via propertyChanged(), and calling unmount() inside detaching() so that React cleans up timers and subscriptions.

Register the Wrapper Component and Use It

Now, register the wrapper component with Aurelia and then use it in your application.

Then, reference the wrapper in a view:

Ensure you import and make the React component available in your Aurelia component:

Advanced Integration Patterns

Error Boundaries

For production applications, consider wrapping React components in error boundaries:

Then modify your wrapper to use the error boundary:

React Root Error Hooks

React 19 exposes additional root options, letting you hook into caught or uncaught errors even before they reach an error boundary. Add another bindable for rootOptions and pass it to createRoot when you need centralized logging:

You can populate rootOptions from Aurelia with callbacks such as:

Wire it up in the view: <react-wrapper root-options.bind="reactRootOptions" ...></react-wrapper>.

React 18+ and 19 Compatibility

This integration pattern embraces the React DOM client API introduced in React 18 and retained in React 19:

  • createRoot is the entry point to Concurrent React. Using it ensures your embedded components can opt into features like transitions without any extra glue.

  • React 18+ automatically batches state updates, so React components you host inside Aurelia get predictable renders even if multiple Aurelia bindings mutate the props in the same tick.

  • React 19 ships improved TypeScript definitions and keeps the expanded root options (onCaughtError, onUncaughtError, and onRecoverableError), letting you consolidate error handling in one place.

Performance Considerations

  • React components are re-rendered when props change via Aurelia's propertyChanged() lifecycle

  • Use React.memo() (or PureComponent) for expensive components to prevent unnecessary re-renders when Aurelia pushes the same data reference

  • Avoid recreating prop objects inline in your view—store them on the view-model so Aurelia only notifies React when values actually change

  • Consider implementing shouldComponentUpdate logic or memoization in the React component itself for fine-grained control

Following these steps, you can integrate React components into your Aurelia 2 application. This process highlights the flexibility of Aurelia, allowing you to take advantage of React's component library while enjoying the benefits of Aurelia's powerful features.

Last updated

Was this helpful?