Introducing React-Admin V5

François Zaninotto
#react#react-admin

React-admin v5 is here! This version started as a technical update to clean up the codebase and integrate the latest React features and libraries. However, we ended up adding many new features and improvements that we think you'll love. We've enhanced both the user and developer experiences, making react-admin more powerful and user-friendly. The breaking changes are minimal, ensuring a smooth upgrade for existing apps.

We were unable to confirm your registration.
Your registration is confirmed.

Keep up to date

Join our react-admin newsletter for regular updates. No spam ever.

In a Nutshell

React-admin v5 is a large release! It introduces the following changes:

UI Improvements

  • Apps now have a theme switcher and a dark theme by default (#9479)
  • Inputs now default to full width (#9704)
  • Links are now underlined (#9483)
  • List pages restore scroll position when coming back from Edit and Create views (#9774)
  • Errors in the Layout code now trigger the Error Boundary (#9799)
  • Button size can be set via props (#9735)

App Initialization

  • Simpler custom layout components just need to render their children (#9591)
  • No more props drilling for Layout, AppBar, Menu, etc (#9591)
  • useDefaultTitle() hook returns the application title from anywhere in the app (#9591)

Data Providers

  • Data providers can now cancel queries for unmounted components (opt-in) (#9612)
  • GraphQL data providers are easier to initialize (they are now synchronous) (#9820)
  • GraphQL-Simple data provider supports Sparse Fields in queries (#9392)
  • GraphQL-Simple data provider supports updateMany and deleteMany mutations (#9393)
  • withLifecycleCallbacks now supports wildcard and array of callbacks (#9577)
  • Middlewares are more powerful and handle errors better (#9875)

List pages

  • Datagrid has rowClick enabled by default, it links to the edit or show view depending on the resource definition (#9466)
  • List bulkActionButtons is now a Datagrid prop (#9707)
  • setFilters doesn't debounce by default, so custom filters work as expected (#9682)
  • List parameters persistence in the store can be disabled (#9742)

Forms & Inputs

  • Inputs no longer require to be touched to display a validation error (#9781)
  • ReferenceInputs are now smarter by default as they use the recordRepresentation (#9902)
  • Server-Side validation is now more robust (#9848)
  • warnWhenUnsavedChanges works again (#9657)
  • Smart input components like TranslatableInputs, ArrayInput, or ReferenceManyInput now compose more seamlessly thanks to a new SourceContext. There is no need for getSource in FormDataConsumer. (#9533)
  • All inputs now have a unique ID - no more duplicate ID warnings (#9788)
  • Learning Forms is facilitated by a new Form chapter in the doc (#9864)

DX Improvements

  • The default Record Representation for resources is now smarter (#9650)
  • Data provider hooks like useGetOne have a smart return type based on the request state. This will force you to plan for the error case. (#9743)
  • Stricter TypeScript types will detect more errors at compile time (#9741)
  • PropTypes are gone, so there is no conflict with TypeScript types (#9851)
  • create-react-admin can run in non-interactive mode (#9544)
  • ra-data-fakerest accepts a delay parameter to simulate network delays (#9908)
  • data-generator-retail now exposes types for the generated data (#9764)

Bump dependencies

  • React-admin requires React 18 to leverage Concurrent React (#9827)
  • React-admin uses the latest version of react-router, react-query, date-fns, fakerest, etc. (#9657, #9473, #9812, #9801, #9908)
  • Internet Explorer is no longer supported (#9530)

React-admin v5

How To Upgrade

The upgrade guide lists all the changes you need to make to upgrade your v4 app to v5. We estimate that a react-admin app with 50,000 lines of code will require about 2 days of work to upgrade to v5.

Start by changing the version of react-admin packages in your package.json:

{
-  "react-admin": "^4.0.0",
-  "ra-data-simplerest": "^4.0.0",
-  "ra-language-english": "^4.0.0",
+  "react-admin": "^5.0.0",
+  "ra-data-simplerest": "^5.0.0",
+  "ra-language-english": "^5.0.0",
}

Then, follow the instructions in the upgrade guide, fix the TypeScript errors, and you should be good to go.

The upgrade work mostly concerns central components like the Layout, AppBar, and Menu. You may need to update a large number of files to rename packages or components (e.g. use @tanstack/react-query instead of react-query), but this can be automated and we provide codemods. The stricter TypeScript types will also prevent you from compiling at first, but this is a good thing as it will help you catch more errors at compile time.

Now, let's zoom in on some of the changes in v5.

Better Forms

Forms play a crucial role in react-admin apps. In version 5, we have made them more appealing with consistent input width by default.

BeforeAfter
Forms in v4Forms in v5

In addition, it simplifies the creation of complex form designs that feature multiple columns.

In v5, we've also extended the flexibility of input components by introducing a new SourceContext that allows you to define subforms.

For instance, the following order edition form leverages <ArrayInput> to edit the order items:

const OrderEdit = () => (
    <Edit>
        <SimpleForm>
            <TextInput source="customer" />
            <DateInput source="date" />
            <ArrayInput source="items">
                <SimpleFormIterator inline>
                    <TextInput source="name" />
                    <NumberInput source="price" />
                    <NumberInput source="quantity" />
                </SimpleFormIterator>
            </ArrayInput>
        </SimpleForm>
    </Edit>
);

Notice that the source prop of the <SimpleFormIterator> children only contains the field name (name, price, quantity). Behind the curtain, <SimpleFormIterator> creates a context for each array item with a source prefix (e.g. items[0]., items[1]., etc.). The Input components read this context and automatically prepend the source.

React-admin v4 was already able to do this, but it used to clone the input components to modify their source for each array item. This limited the ability to compose inputs. In v5, the new SourceContext makes it possible to use other smart components as children of <SimpleFormIterator>.

So for instance, you can compose an <ArrayInput> with <TranslatableInputs> to edit a complex multilingual page object:

const PageEdit = () => (
    <Edit>
        <SimpleForm>
            <TextInput source="title" />
            <ArrayInput source="zones">
                <SimpleFormIterator>
                    <SelectInput source="type" choices={typeOptions} />
                    <TranslatableInputs locales={['en', 'fr']}>
                        <TextInput source="title" />
                        <TextInput source="description" />
                    </TranslatableInputs>
                    <ImageInput source="image" />
                </SimpleFormIterator>
            </ArrayInput>
        </SimpleForm>
    </Edit>
);

You never need to set the SourceContext manually. It's done automatically by the form components that accept descendent inputs.

In React-admin v5, we've also refactored the mutation middlewares that allow smart input components to execute side effects before or after the form is submitted. This allows you to edit one main record and its related records in a single form submission, for instance, a product with its variants:

const ProductEdit = () => (
    <Edit mutationMode="optimistic">
        <SimpleForm>
            <TextInput source="name" />
            <NumberInput source="price" />
            <ReferenceInput source="category_id" reference="categories" />
            <ReferenceManyInput reference="variants" target="product_id">
                <SimpleFormIterator inline>
                    <TextInput source="sku" />
                    <SelectInput source="size" choices={sizes} />
                    <SelectInput source="color" choices={colors} />
                    <NumberInput source="stock" defaultValue={0} />
                </SimpleFormIterator>
            </ReferenceManyInput>
        </SimpleForm>
    </Edit>
);

<ReferenceManyInput> uses the <SourceContext> to prefix the source of its descendants. It leverages mutation middlewares to extract the variants from the form data, save them in a separate API call, and update the main product.

Because it uses the <SourceContext>, <ReferenceManyInput> can be composed with <ArrayInput> or <TranslatableInputs> to create complex forms with ease. And because it uses the new middlewares, the save button is disabled until all the variants are saved.

TypeScript error

TypeScript: Your New Best Friend

All react-admin packages now use the strictNullChecks TypeScript option. This means that TypeScript will catch more errors at compile time, especially when you forget to test if a nullable value is null or undefined, as in the return value for the useRecordContext hook:

const MyComponent = () => {
    const record = useRecordContext();
+   if (!record) return null; // without this line, TS complains about the record below
    return (
        <div>
            <h1>{record.title}</h1>
            <p>{record.body}</p>
        </div>
    );
};

We've also improved the return type of the data provider hooks to let TypeScript narrow down the type of data and error based on the request state. This will force you to plan for the error case:

const MyCustomList = () => {
    const { data, error, isPending } = useListContext();
    if (isPending) return <Loading />;
+   if (error) return <Error />; // without this line, TS complains about data below
    return (
        <ul>
            {data.map(record => (
                <li key={record.id}>{record.name}</li>
            ))}
        </ul>
    );
};

The types of react-admin v5 hooks and components may increase the compilation time for developers, but this trade-off helps prevent runtime bugs that went unnoticed in v4.

Easy Skinning

Most react-admin apps have a custom theme and layout, to match the company's branding. In v5, a custom layout is as simple as a component with a children prop:

// in src/MyLayout.js
export const MyLayout = ({ children }) => (
    <div>
        <h1>My App</h1>
        <main>{children}</main>
    </div>
);

// in src/App.js
import { Admin } from 'react-admin';
import { dataProvider } from './dataProvider';
import { MyLayout } from './MyLayout';

const App = () => (
    <Admin dataProvider={dataProvider} layout={MyLayout}>
        // ...
    </Admin>
);

React-admin v5 apps support a light and a dark theme, and default to the user system preference.

We've also updated many components to rely on the application theme. This leaves more room to customize the app's look and feel without having to override the sx of the components.

Previous Versions

React-admin v4 is now in maintenance mode. It won't receive any new features, but we'll continue to fix important bugs and security issues. You should plan an upgrade to v5 in the upcoming month to benefit from the latest features and improvements.

React-admin v3 is considered "end of life" and won't receive any more updates. We recommend upgrading to v4 or v5 as soon as possible to avoid security issues.

Enterprise Edition Packages in Beta

We've already started working on upgrading te Enterprise Edition Packages so that they are compatible with react-admin v5. We still have some work to do before we can release them, but they are already available in beta.

If you want to upgrade a react-admin app that depends on EE packages, make sure you target the next version of the EE packages in your package.json:

{
-  "@marmelab/ra-realtime": "^4.5.3",
+  "@marmelab/ra-realtime": "next",
}

Conclusion

It took longer than expected to adjust this new release because we've touched pretty much every file in the react-admin codebase. But this work is the foundation of many new features that we plan to add in the upcoming months.

We hope you'll enjoy this new version and that it will make your react-admin apps even more powerful and user-friendly. We can't wait to see what you'll build with it!

Did you like this article? Share it!