national-gold
national-gold2y ago

Nested Resources

The API that I am integrating with has a lot of nested resources. As an example (i.e not actual api url): GET/POST/PATCH/DELETE https://api.com/v1/resourceA GET/POST/PATCH/DELETE https://api.com/v1/resourceA/resourceAName/resourceB GET/POST/PATCH/DELETE https://api.com/v1/resourceA/resourceAName/resourceB/resourceBName/resourceC What is the best practice way of setting up the data provider for such an API? Should I create a custom data provider for https://api.com/v1, pass in resourceAName as an id, and resourceBName/resourceCName/etc. as metadata? Or should I create separate custom data providers for each resource? Both of these seem a bit convoluted for a use case that seems like it would be common place, so I assume there must be a better way to do this. Thank you!
24 Replies
Omer
Omer2y ago
Hey @misstsuliu 👋, You can use "resource" property of data/form/table hooks 🚀 https://refine.dev/docs/faq/#how-can-i-request-an-api-with-nested-route
FAQ | refine
How can I change the form data before submitting it to the API?
robust-apricot
robust-apricot2y ago
Hi guys, I'm trying to do a nested resource as explained above, but the call to the endpoint doesn't contain the nested resource. On my App resources props I pass the name merchants but in my pages, I provide the resource subpath/merchants to useTable and useForm, but it continues to use the one specified as name merchants without the subpath It seems to work with useTable if I prefix the resource with a slash like /subpath/merchants but then I need to strip that slash in the construction of the url in the dataProvider. Anyway, this trick doesn't seem to work with useForm I'm a bit confused on the correct way to get nested resource working. Anyone can help me with this ?
Omer
Omer2y ago
Hey @moinax , Welcome, we are glad to see you 💯 Nested resource definitions are only used for routing, but you can use the resource property of the data/form/table hooks Example:
useForm({
resource: "subpath/merchants"
});
useForm({
resource: "subpath/merchants"
});
quickest-silver
quickest-silver2y ago
@moinax which package do you import useForm and useTable from ? There should not be any issue with the override when you pass resource prop but let me check 🤔
robust-apricot
robust-apricot2y ago
Mmm, it's coming from the @pankod/refine-antd Thanks. Yep that's how I did it actually, but something goes wrong
quickest-silver
quickest-silver2y ago
checking now, i'll get back to you asap Hey @moinax, sorry for the late response 🙏 I just checked with @pankod/refine-antd@3.70.0 and @pankod/refine-core@3.88.0. Could not reproduce the useTable issue, Once, i thought i did but turns out it was because the network tab in the developer tools only shows the last segment at the name column in network tab 😅 but it was actually sending requests to abc/def (even though it was showing def only) For the useForm, also could not reproduce but I want to mention a case that might help you with this issue or in the future 😅 There was a case about using multiple useForm hooks in a single route let's say you're in posts/edit/15 and you also want to be able to edit the categories inside a modal or some section or anything. You add another useForm with a resource:"categories", but now if we make a request with just knowing the resource in the second useForm, we will be sending a request for categories/15 which is not the intended behavior. So if you pass a resource property to the useForm you also need to pass id as well to avoid unwanted API calls. To get the id, you can use useParams hook from your router provider or you can access the useParams from useRouterContext hook in @pankod/refine-core Can you update your dependencies if they are old and can you check the request details to make sure its sending a request to the wrong endpoint? If so, can you please try to provide a minimal repro, because I could not reproduce the issues we're mentioning 😅 🙏
robust-apricot
robust-apricot2y ago
Thanks a lot, I'll have a look at this right now. For the request in the network tab, I knew it already and that was not the issue ( because my backend was answering a 404 error) 😉 I'll see if my dependencies are up-to-date, but I started a week ago or so, so it should not be that far away. If it doesn't work I'll try to share you a minimal repo
robust-apricot
robust-apricot2y ago
Hello again, I tried with the latest packages, but didn't change a thing. I created a gist with the files I think we need to check https://gist.github.com/Moinax/347ca2cdb775f47d4fb96541fc28da5d Let me know if it's enough for you or if you need something more. The only thing that I didn't mention earlier is the fact that I put the merchants resource into a parent to get a submenu, maybe that's the issue.
Gist
Refine ant-design nested resources
Refine ant-design nested resources. GitHub Gist: instantly share code, notes, and snippets.
quickest-silver
quickest-silver2y ago
Thats the issue probably, we match the resource by the route or mock one with the provided resource and since you have a a subpath defined in the resources prop; its going to match with the merchants resource 🧐 I will going to check this one to fix the confusion but while this is going to fixed, I think you can try defining the resource name as "subpath/merchants" with options.label as "merchants" and options.route as "merchants" 🤔
robust-apricot
robust-apricot2y ago
That's actually what I did initially and work pretty well (except the toaster displaying an encoded version of subpath/merchants in the message). But I was trying this because we have a few nested resources like subpath/merchants/{id}/something/{id} and I wanted to check if it was even possible without doing it full custom BTW, I tried without the parent route, but I still have issues. The list is working as expected, but: 1. When I create a merchants it calls the right endpoint /subpath/merchants but then it redirects to the wrong refine page subpath/merchants instead of merchants 2. When I try to edit a merchants it calls the wrong endpoint /merchants instead of mbrella_pay/merchants
quickest-silver
quickest-silver2y ago
Looks like the first one is also related to the previous issue we’ve talked about. When you do provide a custom resource you also need to set redirect to false 🤔 but this needs to change i think, i dont think this is ever an intended outcome in any case. For the second, that should not happen when you provide a custom resource. I will try to have a look today to have an answer for it 😅
robust-apricot
robust-apricot2y ago
Thanks a lot moinaxLove again, I can't find any documentation on how to build a multi level menu/resource structure like below:
- Organisations: /organisations
-- Organisation: /organisations/{id}
--- Employees: /organisation/{id}/employees
--- Transactions /organisation/{id}/transactions
--- Benefits: /organisation/{id}/benefits
- Organisations: /organisations
-- Organisation: /organisations/{id}
--- Employees: /organisation/{id}/employees
--- Transactions /organisation/{id}/transactions
--- Benefits: /organisation/{id}/benefits
Is it possible without to much pain ? It seems really easy to build a flat structure, but I can't find anything about nested resources filtering. The idea is to be able to filter all sub-resources on the selected organisation. Thanks in advance for your help
quickest-silver
quickest-silver2y ago
Hey @moinax let me get back on my keyboard in couple mins and i will try to give an answer to that 😅
exotic-emerald
exotic-emerald2y ago
Hi! I have a similar issue!
quickest-silver
quickest-silver2y ago
Hey again, First of all this topic and couple similar ones inspired us to change the way we handle routing to let users to be free when they're designing their apps. Hopefully, there will be great changes on this field with our next major release and we're planning do this in near future. Thanks to everyone involved! 🙏 👏 Unfortunately, our <Sider /> component, by default does not support this also, it's same for our routers too. But we offer custom routes that can be defined easily so you can create your routes in any shape you want. (Here's a good starting point if you don't know how https://refine.dev/docs/advanced-tutorials/custom-pages/#public-custom-pages) When you finally define your routes as you like, you can run swizzle command to export & customize the Layout components (It may export multiple components and you can remove them if you want, for now all you need is the <Sider/> component) (To learn more about swizzle, here's the docs: https://refine.dev/docs/packages/documentation/cli/#swizzle) After that, I think the renderTreeView function may become handy while implementing this kind of multi-level menu, it may need some modification but it can give you a hint on how 😅 While you're developing a custom <Sider /> you'll be able to use the refine data hooks just like the other components/pages so it won't be hard to fetch and transform them to create a menu 😅 Let me know if you have any issues while customizing the sider or creating the custom routes, I'll try to answer them as soon as possible 🚀 @los._.ko hope the above message is helpful to you too 😅 When you define a custom route, refine hooks will not be able to get the resource and id parameters from the route and you'll probably need to pass them manually 🤔 But with the next major, we'll definitely have more flexible and simpler API for that 🤣
exotic-emerald
exotic-emerald2y ago
When is the next major planned to be released?
quickest-silver
quickest-silver2y ago
We'll release the roadmap next week and if everything goes well, the release is planned to be in next month. 🙏 We were discussing it to be announce the release to be in Q1 2023 but I think with this message, we'll push ourselves to make it to the next month 🤣 (sorry @core )
exotic-emerald
exotic-emerald2y ago
Big 😄
robust-apricot
robust-apricot2y ago
All right, thanks @aliemirs , in that case I don't think I'll be able to build this in time: the learning curve will be too long while I'm very comfortable building this with NextJs or CRA. I tried ReactAdmin a few years ago and was quickly stuck with custom needs, so I started from scratch instead. I hoped that Refine would help me gain a lot of time to build our internal backoffice, but I still feels like it won't help me that much in that case. Anyway, thank you for your answers and your great job, I hope some day I'll have a simple admin interface to build, so I will finally be able to use this awesome framework.
quickest-silver
quickest-silver2y ago
Sorry to hear that @moinax, we're hoping to win you back with our next release 🙏 🚀
fascinating-indigo
fascinating-indigo2y ago
It's not that big of a deal, I'm handling the use case for parents child resources, it takes more manual work, mostly to define the resource name in the hooks and layout components, but if you were to do it all by yourself with a barebones react app it would be 10x times the work, I've done it multiple times in the past and it's a lot more
quickest-silver
quickest-silver2y ago
Hey @rafaelsorto, currently, we're working on a good solution for this and hoping to release the version by the end of the month. Of course there will be some changes with the next major version but we'll make this one fully backward compatible with no breaking changes and easy to migrate with guides and codemods. 🙏
vicious-gold
vicious-gold6mo ago
Hey @aliemir Is there any documentation around the solution of above problem ? Any example from new released version ? I guess this was Q1 2023 release from above message
metropolitan-bronze
metropolitan-bronze6mo ago
to improve flexibility, routing is completely detached from Refine since version @4 I believe this doc can be helpful https://refine.dev/docs/guides-concepts/usage-with-existing-projects/#quickstart
Usage with Existing Projects | Refine
Integrating Refine into an existing project is as simple as installing @refinedev/core package and importing Refine component into your application.