mayteio / ra-aws-amplify

🎩 Create backends for your aws-amplify project at the speed of light with react-admin
MIT License
42 stars 7 forks source link

dataProvider from useAmplifyDataProvider() is undefined #17

Closed LaszloDev closed 4 years ago

LaszloDev commented 4 years ago

Hey @mayteio, thanks for putting all the work in to get the library that far. I have been looking for one AWS react-admin lib in the past months but seams to have missed it. Started to build my own simple version in the last weeks.

While trying it out I was not able to get the dataProvider returned through the hook. Have to mention that I configured AppSync/Cognito manually with Serverless.com. As the Amplify SDK just wraps the lower level APIs this should not be the issue. Amplify JS without you library is working fine.

image

mayteio commented 4 years ago

Hey @LaszloDev, you're welcome! In theory, you're right. Though the package hasn't been built for this just yet.

When authorizing, we call Auth.currentSession() here: https://github.com/mayteio/ra-aws-amplify/blob/2b31f063cb4f50284f1f754c2d5bcca61c638da2/src/buildAmplifyProvider/getAuthType.ts#L19 So if you're not using the Auth class from aws-amplify you may run into trouble here. I can certainly refactor so you can pass a function to get the JWT token.

The cause of your error is a catch-22 I struggled with. the <Admin /> component expects a dataProvider prop, however we can't create one until the above jwtToken is returned. This causes an error (in my experience) because ra-data-graphql is trying to download the AppSync schema each time the page loads before the JWT is returned.

I have solved this by explicitly passing the schema.json to useAmplifyDataProvider({schema}). This is auto-generated in some cases, or you can use the aws-cli to get it:

$ aws appsync get-introspection-schema --api-id=<<YOUR API ID>> --format=JSON src/graphql/schema.json --profile=<<YOUR AWS CLI PROFILE>>

Unfortunately I haven't found a way around it, i.e. letting ra-data-graphql download the schema from the server. It's definitely a valid issue.

LaszloDev commented 4 years ago

TLTR Fixing the initial question:

While trying it out I was not able to get the dataProvider returned through the hook.

Ok... this was a stupid mistake. The useAmplifyDataProvider hook is obviously not returning the dataProvider on the first render. All you need is to check if the dataProvider is ready so I added a check:

  if (!dataProvider) {
    return <div>Loading...</div>
  }

When the hook triggers the re-render the dataProvider is ready. It is working fine. How did you solve this? Maybe this is something to be added to the Readme.

About the library and AWS

I have solved this by explicitly passing the schema.json to useAmplifyDataProvider({schema}). This is auto-generated in some cases, or you can use the aws-cli to get it:

$ aws appsync get-introspection-schema --api-id=<<YOUR API ID>> --format=JSON src/graphql/schema.json --profile=<<YOUR AWS CLI PROFILE>>

Unfortunately I haven't found a way around it, i.e. letting ra-data-graphql download the schema from the server. It's definitely a valid issue.

Setting up your own AppSync & Cognito and still using the Amplify CLI with amplify codegen is possible. So I was able to generate the schema and did pass it to get the dataProvider via useAmplifyDataProvider. See my fix above.

I haven't looked into the introspection yet, but using pre-generated schemas and providing it at build time seams to be fine for now.

The general issue I see here is more that I haven't found a standard graph schema structure that everyone uses. When looking at this library is you need to have a get<Resource> or list<Resource>s query present: https://github.com/mayteio/ra-aws-amplify/blob/1dd3f8f8d6a48ab9d665e2934c241e2779088afd/src/buildAmplifyProvider/buildAmplifyProvider.ts#L27-L28

While the ra-data-graphql-simple implementation of Marmelab is expecting a just <Resource> and all<Resource>s query: https://github.com/marmelab/react-admin/blob/master/packages/ra-data-graphql-simple/README.md#L66-L75

https://github.com/marmelab/react-admin/blob/master/packages/ra-data-graphql-simple/README.md#expected-graphql-schema

When I change my schema to your naming structure Im able to open an resource page in react-admin without an error.

Authentication with manual Cognito

When authorizing, we call Auth.currentSession() here: https://github.com/mayteio/ra-aws-amplify/blob/2b31f063cb4f50284f1f754c2d5bcca61c638da2/src/buildAmplifyProvider/getAuthType.ts#L19

Will look into authentication now, and create a separate issue for it. Might me able to simplify it based on my past implementation

mayteio commented 4 years ago

I agree about the naming convention - AWS decided to go with listX instead of allX which is annoying. I've tried to be explicit about naming conventions in the documentation where required.

If you can setup the Auth class using custom cognito then it should work out of the box. If you have to pass in a custom authoriser, I can update the package to be able to pass it as an option to useDataProvider, though would like to avoid that as I feel it's mixing concerns auth/data.

Updated the package behind a beta flag on npm. Give it a go and let me know how you get on!