-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
[RFC] Replace Providers by objects #3686
Comments
I forgot #3340: because they are functions, our providers aren't really practical to use in a |
A con I didn't think of: there is an upgrade cost for users, not when injecting providers, but when using them. We can make it so there is no cost when using import { Query } from 'react-admin';
const UserProfile = ({ record }) => (
<Query type="GET_ONE" resource="users" payload={{ id: record.id }}>
{({ data, loading, error }) => {
if (loading) { return <Loading />; }
if (error) { return <p>ERROR</p>; }
return <div>User {data.username}</div>;
}}
</Query>
); To make that work, we'll need to support both the But users will have to make changes to their code using // in src/comments/ApproveButton.js
import {
showNotification,
UPDATE,
withDataProvider,
} from 'react-admin';
class ApproveButton extends Component {
handleClick = () => {
const { dataProvider, dispatch, record } = this.props;
const updatedRecord = { ...record, is_approved: true };
- dataProvider(UPDATE, 'comments', { id: record.id, data: updatedRecord })
+ dataProvider.update('comments', { id: record.id, data: updatedRecord })
.then(() => {
dispatch(showNotification('Comment approved'));
dispatch(push('/comments'));
})
.catch((e) => {
dispatch(showNotification('Error: comment not approved', 'warning'))
});
}
render() {
return <Button label="Approve" onClick={this.handleClick} />;
}
}
ApproveButton.propTypes = {
dataProvider: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
record: PropTypes.object,
};
export default withDataProvider(ApproveButton) I'm afraid that the cost of migration reduces the benefit/cost ratio. That, and the fact that starting such a refactoring will delay the release of v3 by at least a couple weeks. |
For people who don't use TypeScript (and that's 100% of people since we don't publish types yet), this is just cost with no benefit... So I tend to think this is premature. We should only make that change when react-admin types are published, which will not be in v3.0 (too much work). |
I had a revelation while jogging in the woods with my dog: This change can be made in a totally backward-compatible way, because in JavaScript, functions are also objects. So if developers pass a function provider to const convertFunctionAuthProvider = authProvider => {
authProvider.login = args => authProvider(AUTH_LOGIN, args);
authProvider.logout = () => authProvider(AUTH_LOGOUT);
authProvider.error = error => authProvider(AUTH_LOGOUT, error);
authProvider.check = ()=> authProvider(AUTH_CHECK);
return authProvider;
}; That way, both the internal react-admin calls (using methods like This change is therefore a net benefit with no cost for the developers. I'm +1 for incorporating it in v3. |
We've decided to do it, so I'm closing this issue. |
Problems
It's impossible to give useful Typescript types to the
dataProvider
,authProvider
, and (since #3685)i18nProvider
because they are functions accepting atype
parameter as first argument, and with a return value depending on thattype
. This makes writing custom providers a bit harder.Besides, the
switch/case
syntax of providers is sometimes seen as a bad coding practice.Lastly, all the constants we use (like
GET_ONE
,AUTH_LOGOUT
, etc) make the code heavier and longer to write.Proposal
React-admin calls the Provider functions with a message type and arguments. There is another way to do that, more idiomatic to JavaScript: calling methods on an object.
I propose to transform the syntax of all 3 providers so that they can be objects.
For instance, an
authProvider
written as a function:Can be written as an object as follows:
This is very easy to Type using TypeScript. Something like:
Backward Compatibility
This is not a breaking change if react-admin detects that a provider is a function rather than an object, and wraps it inside a converter function:
So we can make it painless for the users, and preserve the large list of available (data-) providers.
Notes
We've been using composition as an argument for using functions for providers. For instance, to use two different providers for two sets of resources:
This is very practical, but nothing you can't do with objects:
What's your take?
I may forget some pros and cons, please comment on this issue to give your opinion!
The text was updated successfully, but these errors were encountered: