Closed noritsune closed 3 months ago
If you assign me this issue, I'm ready to take on the challenge of fixing it.
Hello @noritsune, thank you for the issue. I agree that we can improve the developer experience.
After discussing with the core team, we thought it would be good to keep the current system as it is and add new features for Next.js (App Router).
Here are the steps:
npx refine add resource
/src/components/{resource name}
and, if using Next.js (App Router), add the “use client”
directive to this file.We believe this approach is simpler to implement and improves the developer experience. What are your thoughts?
And of course, I can assign this issue to you. We would be very happy 🙌
Hello, @alicanerdurmaz!
Thank you for your response and for assigning me to this issue.
Am I correct in understanding that according to the proposed modification, both the component and page files will be created under /src/components/{resource name}
and /src/app/{resource name}
respectively?
I don't quite understand why we need the component file in addition to the page file. Could you please explain why a component file is necessary for CRUD operations on the resource? I've gone through the CLI documentation but couldn't find any information regarding this, hence the confusion.
Refine is independent of the route package and can be used with Remix, React Router, Next.js App Router, or Next.js Pages Router. While there may not be an issue currently, we believe that separating the JSX code of resources into components is the correct approach.
For example, when using React Router, we write:
<Route path="/" element={<PostListPage />} />
However, with Next.js, we use a file-based system to achieve the same result. Fundamentally, we believe that the rendered output in this route should be a separate component.
Additionally, the Next.js App Router defaults to server components, but components generated by the Refine CLI cannot run on the server. Therefore, we need to add the "use-client" directive at the top of the file we create. If we create the resource component in /src/app/{resource name}
, unfortunately, we take away the user's ability to use this route on the server.
Thank you for the detailed explanation.
I now understand why the npx refine add resource
command creates a component file instead of a page, and I agree that maintaining this feature makes sense.
Now, regarding your idea of adding an option to the npx refine add resource command—specifically --for-next-app
:
With this option, when executing npx refine add resource, instead of creating a component file, a page.tsx file would be generated under /src/app/{resource name}
following the routing structure. The contents of the file would be almost identical to the current setup, but would use export default function
instead of export const
.
Additionally, it might be beneficial to add a --for-next-page
option for those using the Next.js page router.
Having these options would allow developers using Next.js with Refine to effortlessly generate CRUD pages for their resources without any further modifications, simply by running a command.
The current components need the "use client" directive to be compatible with RSC, but adding this to all files would restrict users. We agree to update the command to include page.tsx
files that correctly import and return these components, but filling page.tsx
with them could limit users.
For example, if we keep resource components in the components folder, we can:
loader()
using tanstack-router, Remix, or react-router-dom.Generating the resource component directly in page.tsx
with the "use client" directive would be like doing this:
<Route
path="posts/list"
Component={() => {
return <div>{/** Generated resource component code */}</div>;
}}
/>
Also, we don't need to add an option to Refine CLI. We can detect the type of application (Next.js, Vite, Remix, etc.) and make the necessary adjustments. The Refine CLI can already do this, but we need extra control for Next.js appdir and pages.
Refine CLI can automatically switch its behavior based on the framework you are using—that's correct, and I didn't know that. Thank you for informing me.
I agree that keeping Refine CLI simple without adding options would be beneficial.
From your explanations so far, I now fully understand what you're trying to convey. So, regarding the new feature you proposed for Next.js (App Router), is it intended to work like this?
npx refine add resource
./src/components/{resource name}
:
use client
directive added at the top.page.tsx
files under /src/app/{resource name}
in the appropriate directory structure:
page.tsx
file returns the corresponding CRUD component generated in step 2.page.tsx
files should not include the use client
directive as they should run on the server.Here is an example of the files that would be generated.
↓/src/components/users/list.tsx
"use client";
import { MuiInferencer } from "@refinedev/inferencer/mui";
export const UserList = () => {
return <MuiInferencer />;
};
↓/src/app/page.tsx
import { UserList } from "@components/users";
export default function UserListPage() {
return (<UserList/>)
}
Refine CLI can automatically switch its behavior based on the framework you are using—that's correct, and I didn't know that. Thank you for informing me.
I agree that keeping Refine CLI simple without adding options would be beneficial.
From your explanations so far, I now fully understand what you're trying to convey. So, regarding the new feature you proposed for Next.js (App Router), is it intended to work like this?
- Execute
npx refine add resource
.Create CRUD component files under
/src/components/{resource name}
:
- These files have the
use client
directive added at the top.Create corresponding CRUD
page.tsx
files under/src/app/{resource name}
in the appropriate directory structure:
- Each
page.tsx
file returns the corresponding CRUD component generated in step 2.page.tsx
files should not include theuse client
directive as they should run on the server.Here is an example of the files that would be generated.
↓
/src/components/users/list.tsx
"use client"; import { MuiInferencer } from "@refinedev/inferencer/mui"; export const UserList = () => { return <MuiInferencer />; };
↓
/src/app/page.tsx
import { UserList } from "@components/users"; export default function UserListPage() { return (<UserList/>) }
Yes, I think this is good.
Thank you. I will now start working on this task.
With thanks to the @noritsune's contribution, we've published this feature with our latest release of @refinedev/cli
🙏
Is your feature request related to a problem? Please describe.
I usually use Refine with Next.js (App Router). The CLI command for adding resources is very convenient.
However, the files generated by the CLI are all components. Each time, I go through the following cumbersome process to convert them into pages:
/src/components/{resource name}
./src/components/{resource name}
to/src/app/{resource name}
./src/app/{resource name}
according to the specifications in _refine_context.tsx. Rename each .tsx file moved in the previous step to page.tsx.export const
in the CRUD pages withexport default function
;export const UsersShow = () => {
export default function UsersShow() {
export const
, the following error will be displayed in the browser when I open the page.Error: The default export is not a React Component in page: "/users/show/[id]"
Describe alternatives you've considered
No response
Additional context
No response
Describe the thing to improve
Below is my request
export default function
.