Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React-admin 3 #263

Merged
merged 7 commits into from
Jan 13, 2020
Merged

React-admin 3 #263

merged 7 commits into from
Jan 13, 2020

Conversation

alanpoulain
Copy link
Member

@alanpoulain alanpoulain commented Jan 3, 2020

Q A
Bug fix? no
New feature? yes
BC breaks? yes
Deprecations? no
Tickets N/A
License MIT
Doc PR N/A

Supersede #257.

Upgrade the Admin for react-admin 3.

It will be a new 2.0 version because of the BC.

Things done:

  • Use hooks instead of classes.
  • AdminGuesser can be used instead of HydraAdmin (to make it clear it's not related to Hydra).
  • A custom resourceSchemaAnalyzer can be pass as a prop of AdminGuesser.
  • A custom history can be pass as a prop.
  • The Hydra data provider is using the new type.
  • Unused code removed and clean up.

@alanpoulain
Copy link
Member Author

@fzaninotto It would be great if you could have a look 🙂

authProvider,
i18nProvider,
history = createHashHistory(),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT about making it configurable to support also browser history?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a prop so you can pass whatever you want (for example an instance of createBrowserHistory).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add info about this change to "Things done:" because it was not possible before :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure 🙂

@yudhir
Copy link

yudhir commented Jan 5, 2020

Thanks, looking Forward .

@Deuchnord
Copy link

Deuchnord commented Jan 6, 2020

Tested on a fresh project after an npm uninstall @api-platform/admin && npm install --save alanpoulain/admin#ra3 && docker-compose up --build, didn't find any regression. 👍

Copy link
Contributor

@mauchede mauchede left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job @alanpoulain 👍

Copy link
Contributor

@fzaninotto fzaninotto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Encouraging!

loading: false,
},
)}
{AdminGuesserComponent({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's strange (and misleading) to call a component function instead of rendering it. See https://kentcdodds.com/blog/dont-call-a-react-function-component for details.

Why don't you do

 <Provider store={store}>
   <AdminGuesserComponent error="..." resources={resources} fetching={false} />
</Provider>

?

Copy link
Member Author

@alanpoulain alanpoulain Jan 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it has been done this way because the ShallowRenderer from react-test-renderer only allows to render the component "one level deep" and using the Provider is necessary.
See: https://reactjs.org/docs/shallow-renderer.html#overview

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean in tests? Then don't use shallow rendering, use react-testing-library instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Provider was not needed anymore so we can keep the react-test-renderer.

<Loading />
</TranslationProvider>
);
export const AdminGuesserComponent = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"XXXComponent" is a bad name for a component. You don't name your classes "XXXClass", do you?

@@ -0,0 +1,11 @@
root = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it normal that you commit this file? It feels user based, not project based.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fzaninotto The whole purpose of this file is to define common options for files' formatting, so everyone working on the project can (with support from IDEs) enforce the same configuration without any manual work. With this you won't get unintentional whitespace diffs. It should be commited to work.

The question is: do project maintainers want this file and current configuration fits project's standards?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good to me (we have it on every other API Platform projects).

README.md Outdated
import ReactDOM from 'react-dom';
import { AdminGuesser, hydra } from '@api-platform/admin';

const Admin = () => <AdminGuesser dataProvider={hydra.dataProvider("https://demo.api-platform.com")} resourceSchemaAnalyzer={hydra.resourceSchemaAnalyzer()} /> // Use your custom data provider or resource schema analyzer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add line breaks to make it more readable.

Hint: ask prettier to do it for you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, resourceSchemaAnalyzer is long. Why not simply use schemaAnalyzer?

README.md Outdated
```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { AdminGuesser, hydra } from '@api-platform/admin';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name hydra is very vague IMO. What does this object do? Why don't you export a hydraDataProvider and a hydraResourceSchemaAnalyzer directly?

@@ -0,0 +1,68 @@
const getReferenceNameField = reference => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire file is hard to read and would greatly benefit from input/output examples in jsDoc.

import {Loading, useDataProvider} from 'react-admin';
import ResourceSchemaAnalyzerContext from './ResourceSchemaAnalyzerContext';

const IntrospecterComponent = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad name for a component. By the way, why does this file split its logic in two components that are entirely intricated?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For testing purpose, IIRC.


useEffect(() => {
dataProvider
.introspect()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I understanding correctly: as Introspecter is called in every Guesser, this will fetch the entire hydra schema once for each resource, field, input? If so, that's a huge waste of bandwidth and a major slowdown. Especially since you've already fetched the resources in AdminGuesser.

Copy link
Member

@dunglas dunglas Jan 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The introspection logic is only called once, then the result is stored in a local cache and reused.

if (apiSchema) return Promise.resolve({data: apiSchema});


render() {
const {resourceSchema, fields, ...props} = this.props;
setOrderParameters(resolvedOrderParameters);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why you setState here even though resolvedOrderParameters might be empty, and you'll have to call the resourceSchema just next line to set it again.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems it's because sometimes the order parameters are already in the parsed schema, and sometimes it's not and a supplementary call to the API is needed in order to retrieve them. I'm not sure why but maybe @dunglas or @mauchede can answer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, Hydra doesn't support (yet) to expose available filters in docs.jsonld, this information is only available in the metadata of the collection, so a call to the 1st page is needed to retrieve these parameters.

</List>
);
if (!children) {
children = fields.map(field => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't set a new value for a function argument

@alanpoulain
Copy link
Member Author

The Introspecter now uses the useQueryWithStore hook in order to work under optimistic mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants