github refinedev/refine @refinedev/core@4.1.0

refinev4

✨ We are thrilled to announce that the refine v4 is now officially released! ✨

After a year since the release of v3, we have addressed the most requested and questioned areas by the community. refine v4 features better developer experience, and new functionalities to simplify the work of developers. It has also been designed to make refine accessible on all platforms that support React, and to ensure that it can be seamlessly integrated into new and existing projects.

Throughout the development process, we have carefully analyzed feedback, discussions, and questions raised by the community to enhance the framework. We value ongoing feedback and requests, as they will help us to continue improving and evolving refine.

With 100% backward compatibility, users can rest assured that their applications will continue to function as expected with the latest update.

📒Migration Guide: https://refine.dev/docs/migration-guide/3x-to-4x/

What is new in refine v4? 🔥

  • refine v4 includes several new features that are designed to enhance the Developer Experience. We have introduced abstractions and techniques that make it easier for developers to manage concerns such as data management, routing, authorization, layouts, and more, without limiting the functionality of other tools and libraries they may prefer to use.
  • One of the best things about v4 is that it provides 100% backward compatibility, so users can update to the latest version with confidence that their applications will continue to function as expected.
  • Thanks to full codemod support, the entire upgrade process will be automatically updated when you migrate your refine project to v4.

🪄 Migrating your project automatically with refine-codemod ✨

We are putting an end to the developer effort that would take hours.

As the refine team, we use many open-source projects and we are sensitive to breaking changes and version upgrades, which can be challenging. Therefore, for four versions, we have been managing all changes with codemod, and we are delighted about it!

@refinedev/codemod package handles the breaking changes for your project automatically, without any manual steps. It migrates your project from 3.x.x to 4.x.x.

npx @refinedev/codemod@latest refine3-to-refine4

The process is complete, and your project now uses refine@4.x.x. 🚀

Refer to Migration guide for details

New features and improvements🚀

⭐ Bring your own router

  • Routes is now completely detached from refine
  • We have made significant changes to the routerProvider and route handling to improve flexibility and provide unlimited customization options, in response to requests from our community.
  • routerProvider is now optional and you can use refine without a router.
  • We eliminated the need for a specific way of defining routes by simplifying routerProvider to act solely as a link between refine and the router. This allows any router to be used with "refine".
  • Users can integrate refine into their existing projects without needing to modify their current routes or application structure.
  • With its flexible structure, refine now supports React, Remix, Next.js, and Remix platforms, providing a seamless experience for developers. This is also a promising sign that refine will soon provide support for React Native.

⭐ Enterprise-grade routing

  • We now offer top-notch support for routes for resources. With this new feature, you have complete freedom to create routes that can be tailored to meet the specific needs of your advanced and enterprise use cases. There are no limits or restrictions, so you can create routes that truly fit your unique requirements.
  • You can define your actions (list, create, edit, show, clone) as paths rather than components. This will allow you to defining custom routes for actions and also using the full potential of your router without being restricted to the routes created automatically.

⭐ Reduced bundle size

  • To improve performance and optimize bundle size, we have removed re-exported packages from refine.
  • While re-exporting can offer advantages such as allowing packages to be used without being loaded, it can also lead to issues with bundle size.
  • In response to feedback from the community, we made this change as bundle size has become increasingly important for React-based frameworks like refine that support various CRUD applications with the help of Remix and Next.js.
  • Removing re-exported packages enables you to achieve the same bundle size as a vanilla React project.

⭐ New Auth Provider

  • refine v4 introduces a common interface for the authProvider methods to improve transparency for developers and facilitate better understanding and debugging. Previously, developers had to resolve the authProvider methods upon success and reject them upon failure.
  • With the latest update, authProvider methods in refine v4 will always return a resolved promise containing an object with a success key. This key indicates whether the operation was successful or not. In case of failure, an optional error key carrying an Error object can be used to notify users.

Refer to AuthProvider Migration Guide for all implemented updates

Changelog 📗

The following refine packages includes component and hook updates. You can view the details on migration guide by clicking to each one.

We'll show some of new features and updates below. You can view the full changelog

@refinedev/core Updates

Changes in resources

Now you can define actions in multiple ways;
i. As a path

<Refine
    resources={[
        {
            name: "posts",
            list: "/posts",
        },
    ]}
>
    ...
</Refine>

ii. As a component

import { PostList } from "src/posts";

<Refine
    resources={[
        {
            name: "posts",
            list: PostList,
        },
    ]}
>
    ...
</Refine>;

iii. As both

import { PostList } from "src/posts";

<Refine
    resources={[
        {
            name: "posts",
            list: {
                path: "/posts",
                component: PostList,
            },
        },
    ]}
>
    ...
</Refine>;

Nested routes

Now, refine supports nested routes with parameters. You can define the action paths for a resource with parameters. Parameters will be filled with the current ones in the URL and additional ones can be provided via meta properties in hooks and components.

<Refine
    resources={[
        {
            name: "posts",
            list: "users/:authorId/posts",
            show: "users/:authorId/posts/:id",
        },
    ]}
>

Changes in routerProvider

  • routerProvider is now smaller and more flexible. It only contains the following properties;
    • Link: A component that accepts to prop and renders a link to the given path.
    • go: A function that returns a function that accepts a config object and navigates to the given path.
    • back: A function that returns a function that navigates back to the previous page.
    • parse: A function that returns a function that returns the resource, id, action and additional params from the given path. This is the refine's way to communicate with the router library.

@refinedev/antd Updates

  • meta property changes in components
    It can be used to pass additional parameters to the navigation paths.
    For a posts resource definition like this:
<Refine
    resources={[
        {
            name: "posts",
            list: "/posts",
            show: "/:authorId/posts/:id",
        }
    ]}
>

You can pass authorId to the ShowButton component like this:

<ShowButton resource="posts" id="1" meta={{ authorId: 123 }}>

This will navigate to /123/posts/1 path.

  • syncWithLocation support in useDrawerForm and useModalForm hooks
  • useTable return values and properties are updated.
    -useSimpleList hook will not accept all of <List> component properties

Deprecated Components and Removed props

  • ignoreAccessControlProvider prop is removed from buttons.
  • useCheckboxGroup, useSelect, useRadioGroup's' sort prop is now deprecated. Use sorters prop instead.
  • useImport's resourceName prop is now deprecated. Use resource prop instead.
  • <ReadyPage> is now deprecated.
  • Deprecated useMenu removed from @refinedev/antd package. Use useMenu from @refinedev/core package instead

Migrating automatically with Codemod

@pankod/refine-codemod package handles the breaking changes for your project automatically, without any manual steps.

npx @pankod/refine-codemod antd4-to-antd5

And it's done. Now your project uses @pankod/refine-antd@4.x.x.

@refinedev/mui Updates

  • Updated buttons with resource property. resourceNameOrRouteName is now deprecated but kept working until next major version.
  • Deprecated useMenu removed from @refinedev/mui package. Use useMenu from @refinedev/core package instead.

Removed props

  • ignoreAccessControlProvider prop is removed from buttons.
  • cardProps, cardHeaderProps, cardContentProps, cardActionsProps and actionButtons props are removed from CRUD component.
  • useAutocomplete's sort prop is now deprecated. Use sorters prop instead.
  • initialCurrent and initialPageSize props are now deprecated. Use pagination prop instead.
useDataGrid({
-    initialCurrent,
-    initialPageSize,
+    pagination: {
+        current,
+        pageSize,
+    },
})
  • hasPaginationprop is now deprecated. Usepagination.mode` instead.
useDataGrid({
-    hasPagination,
+    pagination: {
+        mode: "off" | "server" | "client",
+    },
}) 
  • sorter and setSorter return values are now deprecated. Use sorters and setSorters instead.
  • All Material UI components re-exported from @refinedev/mui have been removed. You should import them from Material UI packages directly.
npm install @mui/material @emotion/react @emotion/styled @mui/lab @mui/x-data-grid
# or
pnpm add @mui/material @emotion/react @emotion/styled @mui/lab @mui/x-data-grid
# or
yarn add @mui/material @emotion/react @emotion/styled @mui/lab @mui/x-data-grid

After that, you can import them from related packages directly.

- import {
-    Box,
-    NumberField,
-    Stack,
-    Typography,
-    ThemeProvider,
-    DataGrid
-    LoadingButton,
- } from "@refinedev/mui";

+ import { NumberField } from "@refinedev/mui";
+ import { ThemeProvider } from "@mui/material/styles";
+ import { Box, Stack, Typography } from "@mui/material";
+ import { DataGrid } from "@mui/x-data-grid";
+ import { LoadingButton } from "@mui/lab";

@refinedev/mantine Updates

  • meta prop is added
  • syncWithLocation support in useModalForm hook
  • ignoreAccessControlProvider prop is removed from buttons.
  • <ReadyPage> isnow deprecated.
  • Created a <WelcomePage> component to welcome users.
  • Updated buttons with resource property. resourceNameOrRouteName is now deprecated but kept working until next major version.

@refinedev/chakra-ui Updates

@refinedev/react-table Updates

Minor Changes

npm install @tanstack/react-table
# or
pnpm add @tanstack/react-table
# or
yarn add @tanstack/react-table
After that, you can import them from `@tanstack/react-table` package directly.
- import { useTable, ColumnDef, flexRender } from "@refinedev/react-table";

+ import { useTable } from "@refinedev/react-table";
+ import { ColumnDef, flexRender } from "@tanstack/react-table";
  • initialCurrent and initialPageSize props are now deprecated. Use pagination prop instead.
useTable({
-    initialCurrent,
-    initialPageSize,
+    pagination: {
+        current,
+        pageSize,
+    },
})
  • Update type declaration generation with tsc instead of tsup for better navigation throughout projects source code.
  • Only or was supported as a conditional filter. Now and and or can be used together and nested. 🚀
{
operator: "or",
value: [
{
operator: "and",
value: [
  {
    field: "name",
    operator: "eq",
    value: "John Doe",
  },
  {
    field: "age",
    operator: "eq",
    value: 30,
  },
],
},
{
operator: "and",
value: [
  {
    field: "name",
    operator: "eq",
    value: "JR Doe",
  },
  {
    field: "age",
    operator: "eq",
    value: 1,
  },
],
},
],
}
  • Add hasPagination property to useTable hook to enable/disable pagination.
    • useTable return values and properties are updated.
    • initialCurrent and initialPageSize props are now deprecated. Use pagination prop instead.
    • To ensure backward compatibility, initialCurrent and initialPageSize props will work as before.
useTable({
-    initialCurrent,
-    initialPageSize,
+    pagination: {
+        current,
+        pageSize,
+    },
})
-   `hasPagination` prop is now deprecated. Use `pagination.mode` instead.
-   To ensure backward compatibility, `hasPagination` prop will work as before.
useTable({
    refineCoreProps: {
-      hasPagination,
+       pagination: {
+           mode: "off" | "server" | "client",
+       },
    },
})
-   `initialSorter` and `permanentSorter` props are now deprecated. Use `sorters.initial` and `sorters.permanent` instead.
-   `initialFilter`, `permanentFilter`, and `defaultSetFilterBehavior` props are now deprecated. Use `filters.initial`, `filters.permanent`, and `filters.defaultBehavior` instead.
useTable({
    refineCoreProps: {
-      initialFilter,
-      permanentFilter,
-      defaultSetFilterBehavior,
+      filters: {
+          initial,
+          permanent,
+          defaultBehavior,
+      },
    },
})
-   `sorter` and `setSorter` return values are now deprecated. Use `sorters` and `setSorters` instead.
-   To ensure backward compatibility, `sorter` and `setSorter` return values will work as before.
  • Add hasPagination property to useTable hook to enable/disable pagination.
  • Update type declaration generation with tsc instead of tsup for better navigation throughout projects source code.

Patch Changes

@refinedev/react-hook-form

Minor Changes

npm install react-hook-form
# or
pnpm add react-hook-form
# or
yarn add react-hook-form
After that, you can import them from `react-hook-form` package directly.
- import { useForm, Controller } from "@refinedev/react-hook-form";

+ import { useForm } from "@refinedev/react-hook-form";
+ import { Controller } from "react-hook-form";
  • Updated the components to match the changes in routing system of @refinedev/core.

Patch Changes

@refinedev/react-router-v6

Minor Changes

We're releasing a new way to connect your router to refine.

The legacy routerProvider and its exports are now deprecated but accessible at @refinedev/react-router-v6/legacy path.

The new routerBindings are smaller and more flexible than the previos one.

New routerBindings export

New routerBindings contains following properties;

  • go: Which returns a function to handle the navigation in react-router-v6. It accepts a config object and navigates to the given path. Uses useNavigate hook under the hood.
  • back: Which returns a function to handle the navigation in react-router-v6. It navigates back to the previous page. Uses useNavigate hook under the hood.
  • parse: Which returns a function to parse the given path and returns the resource, id, action and additional params. Uses useParams and useLocation hooks and qs package under the hood.
  • Link: A component that accepts to prop and renders a link to the given path. Uses Link component from react-router-dom under the hood.

Complemetary Components

  • RefineRoutes - A component that renders the routes for the resources when the actions are defined as components. This can be used to achieve the legacy behavior of routerProvider prop. RefineRoutes component accepts a render function as a child and passed a JSX.Element array containing Route components for the resource routes. You can wrap it to a Routes component and let it handle the route creation process for you. Additionally, If you want to add custom routes, you can place them inside the Routes component or you can place an another Routes component. Both apporaches are now valid and accepted by refine.
  • NavigateToResource - A component that navigates to the first list action of the resources array of <Refine>. Optionally, you can pass a resource prop to navigate to list action of the resource. This can be placed at the index route of your app to redirect to the first resource.
  • UnsavedChangesNotifier - This component handles the prompt when the user tries to leave the page with unsaved changes. It can be placed under the Refine component.

Exported values from react-router-dom

In earlier versions, we've re-exported the react-router-dom package. This was a bad practice and we've removed it in this version. If you're using react-router-dom in your project, you should install it as a dependency and import the values from it.

@refinedev/nextjs-router

Minor Changes

We're releasing a new way to connect your router to refine.

The legacy routerProvider and its exports are now deprecated but accessible at @refinedev/nextjs-router/legacy-app and @refinedev/nextjs-router/legacy-pages.

The new routerBindings are smaller and more flexible than the previos one.

  • AuthProvider is renamed to LegacyAuthProvider with refine@4. Components and functions are updated to support LegacyAuthProvider.
  • parseTableParams helper is added to let users parse the query params in SSR methods to persist syncWithLocation feature in tables.
  • #3387 a4731bd8fb4 Thanks @vanflux! - Forwarding ref on RefineLink component

Minor Changes

  • #3387 a4731bd8fb4 Thanks @vanflux! - Forwarding ref on RefineLink component
  • #3140 102bfbf3283 Thanks @aliemir! - - Bumped Next.js to 13
  • Added support for experimental appDir option in next.config.js to allow for the latest Next.js features.

pages directory

Current support for pages directory has not changed and will continue to work as before. It will be supported as long as Next.js continues to support and prompts it as the stable way of working with Next.js.

appDir option

appDir option is a new experimental feature in Next.js that introduces a bunch of new features. It is currently in beta and is not stable. It is not recommended to use it in production. But can be used alongside the current pages directory support.

To use appDir option, you need to add it to your next.config.js file.

// next.config.js
module.exports = {
    /* ... */
    experimental: {
        appDir: true,
    },
};

Minor Changes

  • Added handleRefineParams helper function to handle catch-all refine params.
  • Added ability to parse catch-all refine route in Next.js router. This way, instead of creating multiple pages, users can only create one page at the root [[...refine]].tsx and handle all params for the app.
  • Added ability to manage the initial route of refine by binding initialRoute variable to NextRouteComponent component.
  • #2486 ee4d0d112a Thanks @aliemir! - Added handleRefineParams helper function to handle catch-all refine params.
  • #2486 ee4d0d112a Thanks @aliemir! - Added ability to parse catch-all refine route in Next.js router. This way, instead of creating multiple pages, users can only create one page at the root [[...refine]].tsx and handle all params for the app.
  • #2486 ee4d0d112a Thanks @aliemir! - Added ability to manage the initial route of refine by binding initialRoute variable to NextRouteComponent component.
  • Add initialData support to DashboardPage for @pankod/refine-nextjs-router.

@refinedev/remix Updates

  • parseTableParams helper is added to let users parse the query params in loaders to persist syncWithLocation feature in tables.
  • #3779 2acb0cd8ad6 Thanks @aliemir! - Updated the broken Prompt with useBlocker instead of an unsafe workaround.
  • #3779 2acb0cd8ad6 Thanks @aliemir! - Updated the broken Prompt with useBlocker instead of an unsafe workaround.
  • Added ability to manage the initial route of refine by binding initialRoute variable to RemixRouteComponent component.
  • Add splat route support to remix with handleRefineParams helper.
  • Add ability to manage the initial route of refine by binding initialRoute variable to RemixRouteComponent component.
  • Add splat route support to remix with handleRefineParams helper.
  • #2486 ee4d0d112a Thanks @aliemir! - Added ability to manage the initial route of refine by binding initialRoute variable to RemixRouteComponent component.
  • #2486 ee4d0d112a Thanks @aliemir! - Add splat route support to remix with handleRefineParams helper.

Don't miss a new refine release

NewReleases is sending notifications on new releases.