From e8fdf27aa7d8ab4d4239524f8351f0c088907f2c Mon Sep 17 00:00:00 2001 From: zyhou Date: Wed, 15 May 2019 10:12:31 +0200 Subject: [PATCH 01/15] Migrate PostList to hooks --- examples/simple/src/posts/PostList.js | 131 ++++++++++++++------------ 1 file changed, 71 insertions(+), 60 deletions(-) diff --git a/examples/simple/src/posts/PostList.js b/examples/simple/src/posts/PostList.js index 8ebfd9c012a..db5352c066f 100644 --- a/examples/simple/src/posts/PostList.js +++ b/examples/simple/src/posts/PostList.js @@ -1,6 +1,6 @@ import BookIcon from '@material-ui/icons/Book'; import Chip from '@material-ui/core/Chip'; -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import React, { Children, Fragment, cloneElement } from 'react'; import { BooleanField, @@ -46,7 +46,7 @@ const PostFilter = props => ( ); -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ title: { maxWidth: '20em', overflow: 'hidden', @@ -59,7 +59,7 @@ const styles = theme => ({ }, }, publishedAt: { fontStyle: 'italic' }, -}); +})); const PostListBulkActions = props => ( @@ -68,16 +68,21 @@ const PostListBulkActions = props => ( ); -const PostListActionToolbar = withStyles({ +const usePostListActionToolbarStyles = makeStyles({ toolbar: { alignItems: 'center', display: 'flex', }, -})(({ classes, children, ...props }) => ( -
- {Children.map(children, button => cloneElement(button, props))} -
-)); +}); + +const PostListActionToolbar = ({ children, ...props }) => { + const classes = usePostListActionToolbarStyles(); + return ( +
+ {Children.map(children, button => cloneElement(button, props))} +
+ ); +}; const rowClick = (id, basePath, record) => { if (record.commentable) { @@ -91,58 +96,64 @@ const PostPanel = ({ id, record, resource }) => (
); -const PostList = withStyles(styles)(({ classes, ...props }) => ( - - record.title} - secondaryText={record => `${record.views} views`} - tertiaryText={record => - new Date(record.published_at).toLocaleDateString() - } - /> - } - medium={ - - - - { + const classes = useStyles(); + return ( + + record.title} + secondaryText={record => `${record.views} views`} + tertiaryText={record => + new Date(record.published_at).toLocaleDateString() + } /> + } + medium={ + }> + + + - - - - - - - - - - - - - } - /> - -)); + + + + + + + + + + + + + } + /> + + ); +}; export default PostList; From dbb35ec13e7ea84bc6245200425c2c84ebfc7bf4 Mon Sep 17 00:00:00 2001 From: zyhou Date: Wed, 15 May 2019 11:54:52 +0200 Subject: [PATCH 02/15] Migrate PostCreate to hooks --- examples/simple/src/posts/PostCreate.js | 32 ++++++++----------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/examples/simple/src/posts/PostCreate.js b/examples/simple/src/posts/PostCreate.js index 9cf6601bc57..b09e338fe98 100644 --- a/examples/simple/src/posts/PostCreate.js +++ b/examples/simple/src/posts/PostCreate.js @@ -1,5 +1,5 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; +import React from 'react'; +import { useDispatch } from 'react-redux'; import RichTextInput from 'ra-input-rich-text'; import { @@ -24,31 +24,19 @@ import { const saveWithNote = (values, basePath, redirectTo) => crudCreate('posts', { ...values, average_note: 10 }, basePath, redirectTo); -class SaveWithNoteButtonComponent extends Component { - handleClick = () => { - const { basePath, handleSubmit, redirect, saveWithNote } = this.props; +const SaveWithNoteButton = props => { + const dispatch = useDispatch(); + + const handleClick = () => { + const { basePath, handleSubmit, redirect } = props; return handleSubmit(values => { - saveWithNote(values, basePath, redirect); + dispatch(saveWithNote(values, basePath, redirect)); }); }; - render() { - const { handleSubmitWithRedirect, saveWithNote, ...props } = this.props; - - return ( - - ); - } -} - -const SaveWithNoteButton = connect( - undefined, - { saveWithNote } -)(SaveWithNoteButtonComponent); + return ; +}; const PostCreateToolbar = props => ( From 46f7572c909f135ab6f5a837ccae9a6dddc137e3 Mon Sep 17 00:00:00 2001 From: zyhou Date: Wed, 15 May 2019 12:01:17 +0200 Subject: [PATCH 03/15] Migrate ResetViewsButton to hooks --- examples/simple/src/posts/ResetViewsButton.js | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/examples/simple/src/posts/ResetViewsButton.js b/examples/simple/src/posts/ResetViewsButton.js index 8e8fbbe1dfb..a2e56e3aab8 100644 --- a/examples/simple/src/posts/ResetViewsButton.js +++ b/examples/simple/src/posts/ResetViewsButton.js @@ -1,35 +1,33 @@ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; +import { useDispatch } from 'react-redux'; import VisibilityOff from '@material-ui/icons/VisibilityOff'; import { startUndoable, crudUpdateMany, Button } from 'react-admin'; -class ResetViewsAction extends Component { - handleClick = () => { - const { basePath, startUndoable, resource, selectedIds } = this.props; - startUndoable( - crudUpdateMany(resource, selectedIds, { views: 0 }, basePath) +const ResetViewsButton = props => { + const dispatch = useDispatch(); + + const handleClick = () => { + const { basePath, resource, selectedIds } = props; + dispatch( + startUndoable( + crudUpdateMany(resource, selectedIds, { views: 0 }, basePath), + ), ); }; - render() { - return ( - - ); - } -} + return ( + + ); +}; -ResetViewsAction.propTypes = { +ResetViewsButton.propTypes = { basePath: PropTypes.string, label: PropTypes.string, resource: PropTypes.string.isRequired, selectedIds: PropTypes.arrayOf(PropTypes.any).isRequired, - startUndoable: PropTypes.func.isRequired, }; -export default connect( - undefined, - { startUndoable } -)(ResetViewsAction); +export default ResetViewsButton; From ddc2d8bcf2babf498e751a90d0d20f4ade2899f3 Mon Sep 17 00:00:00 2001 From: zyhou Date: Wed, 15 May 2019 13:53:41 +0200 Subject: [PATCH 04/15] Migrate CommentEdit to hooks --- examples/simple/src/comments/CommentEdit.js | 114 ++++++++++---------- 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/examples/simple/src/comments/CommentEdit.js b/examples/simple/src/comments/CommentEdit.js index 645ce7fd52e..e4289e80d7c 100644 --- a/examples/simple/src/comments/CommentEdit.js +++ b/examples/simple/src/comments/CommentEdit.js @@ -1,6 +1,6 @@ import Card from '@material-ui/core/Card'; import Typography from '@material-ui/core/Typography'; -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import React from 'react'; import { AutocompleteInput, @@ -25,7 +25,7 @@ const LinkToRelatedPost = ({ record }) => ( ); -const editStyles = { +const useEditStyles = makeStyles({ actions: { float: 'right', }, @@ -33,63 +33,69 @@ const editStyles = { marginTop: '1em', maxWidth: '30em', }, -}; +}); + +const CommentEdit = props => { + const classes = useEditStyles(); -const CommentEdit = withStyles(editStyles)(({ classes, ...props }) => ( - - {({ resource, record, redirect, save, basePath, version }) => ( -
- - <div className={classes.actions}> - <EditActions - basePath={basePath} - resource={resource} - data={record} - hasShow - hasList + return ( + <EditController {...props}> + {({ resource, record, redirect, save, basePath, version }) => ( + <div className="edit-page"> + <Title + defaultTitle={`Comment #${record ? record.id : ''}`} /> - </div> - <Card className={classes.card}> - {record && ( - <SimpleForm + <div className={classes.actions}> + <EditActions basePath={basePath} - redirect={redirect} resource={resource} - record={record} - save={save} - version={version} - > - <DisabledInput source="id" fullWidth /> - <ReferenceInput - source="post_id" - reference="posts" - perPage={15} - sort={{ field: 'title', order: 'ASC' }} - fullWidth + data={record} + hasShow + hasList + /> + </div> + <Card className={classes.card}> + {record && ( + <SimpleForm + basePath={basePath} + redirect={redirect} + resource={resource} + record={record} + save={save} + version={version} > - <AutocompleteInput - optionText="title" - options={{ fullWidth: true }} + <DisabledInput source="id" fullWidth /> + <ReferenceInput + source="post_id" + reference="posts" + perPage={15} + sort={{ field: 'title', order: 'ASC' }} + fullWidth + > + <AutocompleteInput + optionText="title" + options={{ fullWidth: true }} + /> + </ReferenceInput> + <LinkToRelatedPost /> + <TextInput + source="author.name" + validate={minLength(10)} + fullWidth /> - </ReferenceInput> - <LinkToRelatedPost /> - <TextInput - source="author.name" - validate={minLength(10)} - fullWidth - /> - <DateInput source="created_at" fullWidth /> - <LongTextInput - source="body" - validate={minLength(10)} - fullWidth - /> - </SimpleForm> - )} - </Card> - </div> - )} - </EditController> -)); + <DateInput source="created_at" fullWidth /> + <LongTextInput + source="body" + validate={minLength(10)} + fullWidth + /> + </SimpleForm> + )} + </Card> + </div> + )} + </EditController> + ); +}; export default CommentEdit; From 1f38c918a667bbff57c7108e0c42b6058f0247ad Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Wed, 15 May 2019 13:58:30 +0200 Subject: [PATCH 05/15] Migrate CommentList to hooks --- examples/simple/src/comments/CommentList.js | 128 ++++++++++---------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/examples/simple/src/comments/CommentList.js b/examples/simple/src/comments/CommentList.js index c92aacb7b7d..9c97ff775df 100644 --- a/examples/simple/src/comments/CommentList.js +++ b/examples/simple/src/comments/CommentList.js @@ -10,7 +10,7 @@ import CardContent from '@material-ui/core/CardContent'; import CardHeader from '@material-ui/core/CardHeader'; import Grid from '@material-ui/core/Grid'; import Toolbar from '@material-ui/core/Toolbar'; -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import { unparse as convertToCSV } from 'papaparse/papaparse.min'; import { DateField, @@ -101,7 +101,7 @@ const CommentPagination = ({ ); }; -const listStyles = theme => ({ +const useListStyles = makeStyles(theme => ({ card: { height: '100%', display: 'flex', @@ -118,73 +118,73 @@ const listStyles = theme => ({ cardActions: { justifyContent: 'flex-end', }, -}); +})); -const CommentGrid = withStyles(listStyles)( - ({ classes, ids, data, basePath }) => { - const translate = useTranslate(); - return ( - <Grid spacing={2} container> - {ids.map(id => ( - <Grid item key={id} sm={12} md={6} lg={4}> - <Card className={classes.card}> - <CardHeader - className="comment" - title={ - <TextField - record={data[id]} - source="author.name" - /> - } - subheader={ - <DateField - record={data[id]} - source="created_at" - /> - } - avatar={ - <Avatar> - <PersonIcon /> - </Avatar> - } - /> - <CardContent className={classes.cardContent}> - <TextField record={data[id]} source="body" /> - </CardContent> - <CardContent className={classes.cardLink}> - {translate('comment.list.about')}  - <ReferenceField - resource="comments" - record={data[id]} - source="post_id" - reference="posts" - basePath={basePath} - > - <TextField - source="title" - className={classes.cardLinkLink} - /> - </ReferenceField> - </CardContent> - <CardActions className={classes.cardActions}> - <EditButton - resource="posts" - basePath={basePath} +const CommentGrid = ({ ids, data, basePath }) => { + const translate = useTranslate(); + const classes = useListStyles(); + + return ( + <Grid spacing={2} container style={{ padding: '0 1em' }}> + {ids.map(id => ( + <Grid item key={id} sm={12} md={6} lg={4}> + <Card className={classes.card}> + <CardHeader + className="comment" + title={ + <TextField record={data[id]} + source="author.name" /> - <ShowButton - resource="posts" - basePath={basePath} + } + subheader={ + <DateField record={data[id]} + source="created_at" /> - </CardActions> - </Card> - </Grid> - ))} - </Grid> - ); - } -); + } + avatar={ + <Avatar> + <PersonIcon /> + </Avatar> + } + /> + <CardContent className={classes.cardContent}> + <TextField record={data[id]} source="body" /> + </CardContent> + <CardContent className={classes.cardLink}> + {translate('comment.list.about')}  + <ReferenceField + resource="comments" + record={data[id]} + source="post_id" + reference="posts" + basePath={basePath} + > + <TextField + source="title" + className={classes.cardLinkLink} + /> + </ReferenceField> + </CardContent> + <CardActions className={classes.cardActions}> + <EditButton + resource="posts" + basePath={basePath} + record={data[id]} + /> + <ShowButton + resource="posts" + basePath={basePath} + record={data[id]} + /> + </CardActions> + </Card> + </Grid> + ))} + </Grid> + ); +}; CommentGrid.defaultProps = { data: {}, From 859e0b2c26c7b4569f544f914f2a639a3073f8b7 Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Wed, 15 May 2019 14:20:49 +0200 Subject: [PATCH 06/15] Migrate PostPreview to hooks --- examples/simple/src/comments/PostPreview.js | 38 ++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/examples/simple/src/comments/PostPreview.js b/examples/simple/src/comments/PostPreview.js index f14f4519bf0..f573f9794d9 100644 --- a/examples/simple/src/comments/PostPreview.js +++ b/examples/simple/src/comments/PostPreview.js @@ -1,24 +1,24 @@ import React from 'react'; -import { connect } from 'react-redux'; +import { useSelector } from 'react-redux'; import { SimpleShowLayout, TextField } from 'react-admin'; -const PostPreviewView = ({ isLoading, ...props }) => ( - <SimpleShowLayout {...props}> - <TextField source="id" /> - <TextField source="title" /> - <TextField source="teaser" /> - </SimpleShowLayout> -); +const PostPreview = props => { + const record = useSelector( + state => + state.admin.resources[props.resource] + ? state.admin.resources[props.resource].data[props.id] + : null, + [props.resource, props.id], + ); + const version = useSelector(state => state.admin.ui.viewVersion); -const mapStateToProps = (state, props) => ({ - record: state.admin.resources[props.resource] - ? state.admin.resources[props.resource].data[props.id] - : null, - isLoading: state.admin.loading > 0, - version: state.admin.ui.viewVersion, -}); + return ( + <SimpleShowLayout version={version} record={record} {...props}> + <TextField source="id" /> + <TextField source="title" /> + <TextField source="teaser" /> + </SimpleShowLayout> + ); +}; -export default connect( - mapStateToProps, - {} -)(PostPreviewView); +export default PostPreview; From f415f25180a5bd38ccbf8ca695ddb5a6cf1210f9 Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Wed, 15 May 2019 14:56:57 +0200 Subject: [PATCH 07/15] Migrate PostQuickCreateCancelButton to hooks --- .../src/comments/PostQuickCreateCancelButton.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/simple/src/comments/PostQuickCreateCancelButton.js b/examples/simple/src/comments/PostQuickCreateCancelButton.js index f8c3b306946..65911b6d48c 100644 --- a/examples/simple/src/comments/PostQuickCreateCancelButton.js +++ b/examples/simple/src/comments/PostQuickCreateCancelButton.js @@ -3,11 +3,11 @@ import PropTypes from 'prop-types'; import Button from '@material-ui/core/Button'; import IconCancel from '@material-ui/icons/Cancel'; -import withStyles from '@material-ui/core/styles/withStyles'; +import { makeStyles } from '@material-ui/styles'; import { useTranslate } from 'react-admin'; -const styles = { +const useStyles = makeStyles({ button: { margin: '10px 24px', position: 'relative', @@ -15,10 +15,14 @@ const styles = { iconPaddingStyle: { paddingRight: '0.5em', }, -}; +}); -const CancelButtonView = ({ classes, onClick, label = 'ra.action.cancel' }) => { +const PostQuickCreateCancelButton = ({ + onClick, + label = 'ra.action.cancel', +}) => { const translate = useTranslate(); + const classes = useStyles(); return ( <Button className={classes.button} onClick={onClick}> <IconCancel className={classes.iconPaddingStyle} /> @@ -27,10 +31,9 @@ const CancelButtonView = ({ classes, onClick, label = 'ra.action.cancel' }) => { ); }; -CancelButtonView.propTypes = { - classes: PropTypes.object, +PostQuickCreateCancelButton.propTypes = { label: PropTypes.string, onClick: PropTypes.func.isRequired, }; -export default withStyles(styles)(CancelButtonView); +export default PostQuickCreateCancelButton; From a213f75337f014d8e7bc98db4c61d9b97b8091ad Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Wed, 15 May 2019 15:25:34 +0200 Subject: [PATCH 08/15] Migrate PostReferenceInput to hooks --- .../simple/src/comments/PostReferenceInput.js | 241 ++++++++---------- 1 file changed, 113 insertions(+), 128 deletions(-) diff --git a/examples/simple/src/comments/PostReferenceInput.js b/examples/simple/src/comments/PostReferenceInput.js index b6507f8903a..3eccd38eb12 100644 --- a/examples/simple/src/comments/PostReferenceInput.js +++ b/examples/simple/src/comments/PostReferenceInput.js @@ -1,10 +1,8 @@ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import compose from 'recompose/compose'; +import { useDispatch } from 'react-redux'; import { Field } from 'redux-form'; -import withStyles from '@material-ui/core/styles/withStyles'; +import { makeStyles } from '@material-ui/styles'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; import DialogTitle from '@material-ui/core/DialogTitle'; @@ -15,156 +13,143 @@ import { crudGetMatching, ReferenceInput, SelectInput, - translate, + useTranslate, } from 'react-admin'; // eslint-disable-line import/no-unresolved import PostQuickCreate from './PostQuickCreate'; import PostPreview from './PostPreview'; -const styles = { +const useStyles = makeStyles({ button: { margin: '10px 24px', position: 'relative', }, -}; +}); -class PostReferenceInputView extends React.Component { - static propTypes = { - classes: PropTypes.object.isRequired, - crudGetMatching: PropTypes.func.isRequired, - post_id: PropTypes.any, - translate: PropTypes.func.isRequired, - }; +const PostReferenceInput = props => { + const translate = useTranslate(); + const classes = useStyles(); + const dispatch = useDispatch(); - state = { + const [state, setState] = React.useState({ showCreateDialog: false, showPreviewDialog: false, new_post_id: '', - }; + }); + + React.useEffect( + () => { + //Refresh the choices of the ReferenceInput to ensure our newly created post + // always appear, even after selecting another post + dispatch( + crudGetMatching( + 'posts', + 'comments@post_id', + { page: 1, perPage: 25 }, + { field: 'id', order: 'DESC' }, + {}, + ), + ); + }, + [state.new_post_id], + ); - handleNewClick = event => { + const handleNewClick = event => { event.preventDefault(); - this.setState({ showCreateDialog: true }); + setState({ ...state, showCreateDialog: true }); }; - handleShowClick = event => { + const handleShowClick = event => { event.preventDefault(); - this.setState({ showPreviewDialog: true }); + setState({ ...state, showPreviewDialog: true }); }; - handleCloseCreate = () => { - this.setState({ showCreateDialog: false }); + const handleCloseCreate = () => { + setState({ ...state, showCreateDialog: false }); }; - handleCloseShow = () => { - this.setState({ showPreviewDialog: false }); + const handleCloseShow = () => { + setState({ ...state, showPreviewDialog: false }); }; - handleSave = post => { - const { crudGetMatching } = this.props; - this.setState({ showCreateDialog: false, new_post_id: post.id }, () => { - // Refresh the choices of the ReferenceInput to ensure our newly created post - // always appear, even after selecting another post - crudGetMatching( - 'posts', - 'comments@post_id', - { page: 1, perPage: 25 }, - { field: 'id', order: 'DESC' }, - {} - ); - }); + const handleSave = post => { + setState({ ...state, showCreateDialog: false, new_post_id: post.id }); }; - render() { - const { showCreateDialog, showPreviewDialog, new_post_id } = this.state; - const { classes, translate, ...props } = this.props; - - return ( - <Fragment> - <ReferenceInput {...props} defaultValue={new_post_id}> - <SelectInput optionText="title" /> - </ReferenceInput> - <Button - data-testid="button-add-post" - className={classes.button} - onClick={this.handleNewClick} - > - {translate('ra.action.create')} - </Button> - <Field - name="post_id" - component={({ input }) => - input.value && ( - <Fragment> - <Button - data-testid="button-show-post" - className={classes.button} - onClick={this.handleShowClick} - > - {translate('ra.action.show')} - </Button> - <Dialog - data-testid="dialog-show-post" - fullWidth - open={showPreviewDialog} - onClose={this.handleCloseShow} - aria-label={translate('simple.create-post')} - > - <DialogTitle> - {translate('simple.create-post')} - </DialogTitle> - <DialogContent> - <PostPreview - id={input.value} - basePath="/posts" - resource="posts" - /> - </DialogContent> - <DialogActions> - <Button - data-testid="button-close-modal" - onClick={this.handleCloseShow} - > - {translate('simple.action.close')} - </Button> - </DialogActions> - </Dialog> - </Fragment> - ) - } - /> - <Dialog - data-testid="dialog-add-post" - fullWidth - open={showCreateDialog} - onClose={this.handleCloseCreate} - aria-label={translate('simple.create-post')} - > - <DialogTitle>{translate('simple.create-post')}</DialogTitle> - <DialogContent> - <PostQuickCreate - onCancel={this.handleCloseCreate} - onSave={this.handleSave} - basePath="/posts" - form="post-create" - resource="posts" - /> - </DialogContent> - </Dialog> - </Fragment> - ); - } -} - -const mapDispatchToProps = { - crudGetMatching, + return ( + <Fragment> + <ReferenceInput {...props} defaultValue={state.new_post_id}> + <SelectInput optionText="title" /> + </ReferenceInput> + <Button + data-testid="button-add-post" + className={classes.button} + onClick={handleNewClick} + > + {translate('ra.action.create')} + </Button> + <Field + name="post_id" + component={({ input }) => + input.value && ( + <Fragment> + <Button + data-testid="button-show-post" + className={classes.button} + onClick={handleShowClick} + > + {translate('ra.action.show')} + </Button> + <Dialog + data-testid="dialog-show-post" + fullWidth + open={state.showPreviewDialog} + onClose={handleCloseShow} + aria-label={translate('simple.create-post')} + > + <DialogTitle> + {translate('simple.create-post')} + </DialogTitle> + <DialogContent> + <PostPreview + id={input.value} + basePath="/posts" + resource="posts" + /> + </DialogContent> + <DialogActions> + <Button + data-testid="button-close-modal" + onClick={handleCloseShow} + > + {translate('simple.action.close')} + </Button> + </DialogActions> + </Dialog> + </Fragment> + ) + } + /> + <Dialog + data-testid="dialog-add-post" + fullWidth + open={state.showCreateDialog} + onClose={handleCloseCreate} + aria-label={translate('simple.create-post')} + > + <DialogTitle>{translate('simple.create-post')}</DialogTitle> + <DialogContent> + <PostQuickCreate + onCancel={handleCloseCreate} + onSave={handleSave} + basePath="/posts" + form="post-create" + resource="posts" + /> + </DialogContent> + </Dialog> + </Fragment> + ); }; -export default compose( - connect( - undefined, - mapDispatchToProps - ), - withStyles(styles), - translate -)(PostReferenceInputView); +export default PostReferenceInput; From 1d5a259883ebcc397fcdca7bb0a14f90c520c6d2 Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Wed, 15 May 2019 15:29:29 +0200 Subject: [PATCH 09/15] Migrate UserEdit hooks --- examples/simple/src/tags/TagList.js | 2 -- examples/simple/src/users/UserEdit.js | 21 ++++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/simple/src/tags/TagList.js b/examples/simple/src/tags/TagList.js index c81227682b9..fb8866a1810 100644 --- a/examples/simple/src/tags/TagList.js +++ b/examples/simple/src/tags/TagList.js @@ -5,13 +5,11 @@ import { List, SaveButton, ShowButton, - TextField, TextInput, } from 'react-admin'; import { DragPreview, IgnoreFormProps, - NodeView, NodeForm, Tree, NodeActions, diff --git a/examples/simple/src/users/UserEdit.js b/examples/simple/src/users/UserEdit.js index ef6d758c7a1..9b99a1d9e5c 100644 --- a/examples/simple/src/users/UserEdit.js +++ b/examples/simple/src/users/UserEdit.js @@ -13,29 +13,32 @@ import { Toolbar, required, } from 'react-admin'; -import { withStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/styles'; import UserTitle from './UserTitle'; import Aside from './Aside'; -const toolbarStyles = { +const useToolbarStyles = makeStyles({ toolbar: { display: 'flex', justifyContent: 'space-between', }, -}; +}); /** * Custom Toolbar for the Edit form * * Save with undo, but delete with confirm */ -const UserEditToolbar = withStyles(toolbarStyles)(props => ( - <Toolbar {...props}> - <SaveButton /> - <DeleteWithConfirmButton /> - </Toolbar> -)); +const UserEditToolbar = props => { + const classes = useToolbarStyles(); + return ( + <Toolbar {...props} classes={classes}> + <SaveButton /> + <DeleteWithConfirmButton /> + </Toolbar> + ); +}; const UserEdit = ({ permissions, ...props }) => ( <Edit title={UserTitle} aside={Aside} {...props}> From 13620655e9f6278133f4e20bd96fea709b3a8b65 Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Wed, 15 May 2019 18:11:38 +0200 Subject: [PATCH 10/15] useCallback on all event --- .../simple/src/comments/PostReferenceInput.js | 51 +++++++++---------- examples/simple/src/posts/PostCreate.js | 18 ++++--- examples/simple/src/posts/ResetViewsButton.js | 26 ++++++---- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/examples/simple/src/comments/PostReferenceInput.js b/examples/simple/src/comments/PostReferenceInput.js index 3eccd38eb12..2c79011d48a 100644 --- a/examples/simple/src/comments/PostReferenceInput.js +++ b/examples/simple/src/comments/PostReferenceInput.js @@ -1,4 +1,4 @@ -import React, { Fragment } from 'react'; +import React, { Fragment, useState, useCallback, useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { Field } from 'redux-form'; @@ -31,13 +31,11 @@ const PostReferenceInput = props => { const classes = useStyles(); const dispatch = useDispatch(); - const [state, setState] = React.useState({ - showCreateDialog: false, - showPreviewDialog: false, - new_post_id: '', - }); + const [showCreateDialog, setShowCreateDialog] = useState(false); + const [showPreviewDialog, setShowPreviewDialog] = useState(false); + const [newPostId, setNewPostId] = useState(''); - React.useEffect( + useEffect( () => { //Refresh the choices of the ReferenceInput to ensure our newly created post // always appear, even after selecting another post @@ -51,34 +49,35 @@ const PostReferenceInput = props => { ), ); }, - [state.new_post_id], + [newPostId], ); - const handleNewClick = event => { + const handleNewClick = useCallback(event => { event.preventDefault(); - setState({ ...state, showCreateDialog: true }); - }; + setShowCreateDialog(true); + }, []); - const handleShowClick = event => { + const handleShowClick = useCallback(event => { event.preventDefault(); - setState({ ...state, showPreviewDialog: true }); - }; + setShowPreviewDialog(true); + }, []); - const handleCloseCreate = () => { - setState({ ...state, showCreateDialog: false }); - }; + const handleCloseCreate = useCallback(() => { + setShowCreateDialog(false); + }, []); - const handleCloseShow = () => { - setState({ ...state, showPreviewDialog: false }); - }; + const handleCloseShow = useCallback(() => { + setShowPreviewDialog(false); + }, []); - const handleSave = post => { - setState({ ...state, showCreateDialog: false, new_post_id: post.id }); - }; + const handleSave = useCallback(post => { + setShowCreateDialog(false); + setNewPostId(post.id); + }, []); return ( <Fragment> - <ReferenceInput {...props} defaultValue={state.new_post_id}> + <ReferenceInput {...props} defaultValue={newPostId}> <SelectInput optionText="title" /> </ReferenceInput> <Button @@ -103,7 +102,7 @@ const PostReferenceInput = props => { <Dialog data-testid="dialog-show-post" fullWidth - open={state.showPreviewDialog} + open={showPreviewDialog} onClose={handleCloseShow} aria-label={translate('simple.create-post')} > @@ -133,7 +132,7 @@ const PostReferenceInput = props => { <Dialog data-testid="dialog-add-post" fullWidth - open={state.showCreateDialog} + open={showCreateDialog} onClose={handleCloseCreate} aria-label={translate('simple.create-post')} > diff --git a/examples/simple/src/posts/PostCreate.js b/examples/simple/src/posts/PostCreate.js index b09e338fe98..f2cb6b4fa13 100644 --- a/examples/simple/src/posts/PostCreate.js +++ b/examples/simple/src/posts/PostCreate.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { useDispatch } from 'react-redux'; import RichTextInput from 'ra-input-rich-text'; @@ -26,14 +26,16 @@ const saveWithNote = (values, basePath, redirectTo) => const SaveWithNoteButton = props => { const dispatch = useDispatch(); + const { basePath, handleSubmit, redirect } = props; - const handleClick = () => { - const { basePath, handleSubmit, redirect } = props; - - return handleSubmit(values => { - dispatch(saveWithNote(values, basePath, redirect)); - }); - }; + const handleClick = useCallback( + () => { + return handleSubmit(values => { + dispatch(saveWithNote(values, basePath, redirect)); + }); + }, + [basePath, redirect], + ); return <SaveButton {...props} handleSubmitWithRedirect={handleClick} />; }; diff --git a/examples/simple/src/posts/ResetViewsButton.js b/examples/simple/src/posts/ResetViewsButton.js index a2e56e3aab8..242139cb6a6 100644 --- a/examples/simple/src/posts/ResetViewsButton.js +++ b/examples/simple/src/posts/ResetViewsButton.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; import { useDispatch } from 'react-redux'; import VisibilityOff from '@material-ui/icons/VisibilityOff'; @@ -6,15 +6,23 @@ import { startUndoable, crudUpdateMany, Button } from 'react-admin'; const ResetViewsButton = props => { const dispatch = useDispatch(); + const { basePath, resource, selectedIds } = props; - const handleClick = () => { - const { basePath, resource, selectedIds } = props; - dispatch( - startUndoable( - crudUpdateMany(resource, selectedIds, { views: 0 }, basePath), - ), - ); - }; + const handleClick = useCallback( + () => { + dispatch( + startUndoable( + crudUpdateMany( + resource, + selectedIds, + { views: 0 }, + basePath, + ), + ), + ); + }, + [basePath, resource, selectedIds], + ); return ( <Button label="simple.action.resetViews" onClick={handleClick}> From 5f6c4687d20aff50c5c9edd34f547b9b3589fe0e Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Wed, 15 May 2019 18:12:48 +0200 Subject: [PATCH 11/15] Migrate PostQuickCreate to hook --- .../simple/src/comments/PostQuickCreate.js | 113 +++++++++--------- 1 file changed, 55 insertions(+), 58 deletions(-) diff --git a/examples/simple/src/comments/PostQuickCreate.js b/examples/simple/src/comments/PostQuickCreate.js index a7d3df33e7c..acd65cf4e08 100644 --- a/examples/simple/src/comments/PostQuickCreate.js +++ b/examples/simple/src/comments/PostQuickCreate.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react'; +import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core/styles'; +import { useSelector, useDispatch } from 'react-redux'; +import { makeStyles } from '@material-ui/styles'; import { CREATE, LongTextInput, @@ -10,6 +10,7 @@ import { TextInput, Toolbar, required, + showNotification, } from 'react-admin'; // eslint-disable-line import/no-unresolved import CancelButton from './PostQuickCreateCancelButton'; @@ -28,65 +29,61 @@ PostQuickCreateToolbar.propTypes = { onCancel: PropTypes.func.isRequired, }; -const styles = { +const useStyles = makeStyles({ form: { padding: 0 }, -}; +}); -class PostQuickCreateView extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, - onCancel: PropTypes.func.isRequired, - onSave: PropTypes.func.isRequired, - submitting: PropTypes.bool.isRequired, - }; +const PostQuickCreate = ({ onCancel, onSave }) => { + const classes = useStyles(); + const dispatch = useDispatch(); + const submitting = useSelector(state => state.admin.loading > 0); - handleSave = values => { - const { dispatch, onSave } = this.props; - dispatch({ - type: 'QUICK_CREATE', - payload: { data: values }, - meta: { - fetch: CREATE, - resource: 'posts', - onSuccess: { - callback: ({ payload: { data } }) => onSave(data), - }, - onError: { - callback: ({ error }) => this.setState({ error }), + const handleSave = useCallback( + values => { + dispatch({ + type: 'QUICK_CREATE', + payload: { data: values }, + meta: { + fetch: CREATE, + resource: 'posts', + onSuccess: { + callback: ({ payload: { data } }) => onSave(data), + }, + onError: { + callback: ({ error }) => { + dispatch(showNotification(error.message, 'error')); + }, + }, }, - }, - }); - }; + }); + }, + [onSave], + ); - render() { - const { classes, submitting, onCancel } = this.props; - - return ( - <SimpleForm - form="post-create" - save={this.handleSave} - saving={submitting} - redirect={false} - toolbar={props => ( - <PostQuickCreateToolbar - onCancel={onCancel} - submitting={submitting} - {...props} - /> - )} - classes={{ form: classes.form }} - > - <TextInput source="title" validate={required()} /> - <LongTextInput source="teaser" validate={required()} /> - </SimpleForm> - ); - } -} + return ( + <SimpleForm + form="post-create" + save={handleSave} + saving={submitting} + redirect={false} + toolbar={props => ( + <PostQuickCreateToolbar + onCancel={onCancel} + submitting={submitting} + {...props} + /> + )} + classes={{ form: classes.form }} + > + <TextInput source="title" validate={required()} /> + <LongTextInput source="teaser" validate={required()} /> + </SimpleForm> + ); +}; -const mapStateToProps = state => ({ - submitting: state.admin.loading > 0, -}); +PostQuickCreate.propTypes = { + onCancel: PropTypes.func.isRequired, + onSave: PropTypes.func.isRequired, +}; -export default connect(mapStateToProps)( - withStyles(styles)(PostQuickCreateView) -); +export default PostQuickCreate; From 647aca9be4bb81a463aeaa43c16483fb07fda88c Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Thu, 23 May 2019 22:44:50 +0200 Subject: [PATCH 12/15] Review isLoading --- examples/simple/src/comments/CommentList.js | 2 +- examples/simple/src/comments/PostPreview.js | 1 + examples/simple/src/posts/PostCreate.js | 7 +++---- examples/simple/src/posts/PostList.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/simple/src/comments/CommentList.js b/examples/simple/src/comments/CommentList.js index 9c97ff775df..cd5383c736f 100644 --- a/examples/simple/src/comments/CommentList.js +++ b/examples/simple/src/comments/CommentList.js @@ -125,7 +125,7 @@ const CommentGrid = ({ ids, data, basePath }) => { const classes = useListStyles(); return ( - <Grid spacing={2} container style={{ padding: '0 1em' }}> + <Grid spacing={2} container> {ids.map(id => ( <Grid item key={id} sm={12} md={6} lg={4}> <Card className={classes.card}> diff --git a/examples/simple/src/comments/PostPreview.js b/examples/simple/src/comments/PostPreview.js index f573f9794d9..2063f2a9a40 100644 --- a/examples/simple/src/comments/PostPreview.js +++ b/examples/simple/src/comments/PostPreview.js @@ -11,6 +11,7 @@ const PostPreview = props => { [props.resource, props.id], ); const version = useSelector(state => state.admin.ui.viewVersion); + const isLoading = useSelector(state => state.admin.loading > 0); return ( <SimpleShowLayout version={version} record={record} {...props}> diff --git a/examples/simple/src/posts/PostCreate.js b/examples/simple/src/posts/PostCreate.js index f2cb6b4fa13..b0acfaebfb1 100644 --- a/examples/simple/src/posts/PostCreate.js +++ b/examples/simple/src/posts/PostCreate.js @@ -29,11 +29,10 @@ const SaveWithNoteButton = props => { const { basePath, handleSubmit, redirect } = props; const handleClick = useCallback( - () => { - return handleSubmit(values => { + () => + handleSubmit(values => { dispatch(saveWithNote(values, basePath, redirect)); - }); - }, + }), [basePath, redirect], ); diff --git a/examples/simple/src/posts/PostList.js b/examples/simple/src/posts/PostList.js index db5352c066f..574149aa852 100644 --- a/examples/simple/src/posts/PostList.js +++ b/examples/simple/src/posts/PostList.js @@ -116,7 +116,7 @@ const PostList = props => { /> } medium={ - <Datagrid rowClick={rowClick} expand={<PostPanel />}> + <Datagrid rowClick={rowClick} expand={PostPanel}> <TextField source="id" /> <TextField source="title" From 07ecfbc7ec0f7606fb8242ab8e529863c5cfee0d Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Fri, 24 May 2019 10:21:22 +0200 Subject: [PATCH 13/15] fix bug uselector ? Lets see --- examples/simple/src/comments/PostQuickCreate.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/simple/src/comments/PostQuickCreate.js b/examples/simple/src/comments/PostQuickCreate.js index acd65cf4e08..77158a65491 100644 --- a/examples/simple/src/comments/PostQuickCreate.js +++ b/examples/simple/src/comments/PostQuickCreate.js @@ -1,6 +1,6 @@ import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; -import { useSelector, useDispatch } from 'react-redux'; +import { connect, useSelector, useDispatch } from 'react-redux'; import { makeStyles } from '@material-ui/styles'; import { CREATE, @@ -33,10 +33,9 @@ const useStyles = makeStyles({ form: { padding: 0 }, }); -const PostQuickCreate = ({ onCancel, onSave }) => { +const PostQuickCreateView = ({ submitting, onCancel, onSave }) => { const classes = useStyles(); const dispatch = useDispatch(); - const submitting = useSelector(state => state.admin.loading > 0); const handleSave = useCallback( values => { @@ -81,9 +80,13 @@ const PostQuickCreate = ({ onCancel, onSave }) => { ); }; -PostQuickCreate.propTypes = { +PostQuickCreateView.propTypes = { onCancel: PropTypes.func.isRequired, onSave: PropTypes.func.isRequired, }; -export default PostQuickCreate; +const mapStateToProps = state => ({ + submitting: state.admin.loading > 0, +}); + +export default connect(mapStateToProps)(PostQuickCreateView); From 9b130d09adc44eb98ef231d27d0b0408e182385d Mon Sep 17 00:00:00 2001 From: Francois Zaninotto <fzaninotto@gmail.com> Date: Fri, 24 May 2019 17:33:03 +0200 Subject: [PATCH 14/15] Remove Connect in PostQuickCreate --- .../simple/src/comments/PostQuickCreate.js | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/simple/src/comments/PostQuickCreate.js b/examples/simple/src/comments/PostQuickCreate.js index 77158a65491..94801a47a3e 100644 --- a/examples/simple/src/comments/PostQuickCreate.js +++ b/examples/simple/src/comments/PostQuickCreate.js @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; import { connect, useSelector, useDispatch } from 'react-redux'; import { makeStyles } from '@material-ui/styles'; @@ -33,9 +33,10 @@ const useStyles = makeStyles({ form: { padding: 0 }, }); -const PostQuickCreateView = ({ submitting, onCancel, onSave }) => { +const PostQuickCreate = ({ onCancel, onSave }) => { const classes = useStyles(); const dispatch = useDispatch(); + const submitting = useSelector(state => state.admin.loading > 0); const handleSave = useCallback( values => { @@ -56,7 +57,7 @@ const PostQuickCreateView = ({ submitting, onCancel, onSave }) => { }, }); }, - [onSave], + [onSave] ); return ( @@ -65,12 +66,15 @@ const PostQuickCreateView = ({ submitting, onCancel, onSave }) => { save={handleSave} saving={submitting} redirect={false} - toolbar={props => ( - <PostQuickCreateToolbar - onCancel={onCancel} - submitting={submitting} - {...props} - /> + toolbar={useMemo( + () => props => ( + <PostQuickCreateToolbar + onCancel={onCancel} + submitting={submitting} + {...props} + /> + ), + [onCancel, submitting] )} classes={{ form: classes.form }} > @@ -80,13 +84,9 @@ const PostQuickCreateView = ({ submitting, onCancel, onSave }) => { ); }; -PostQuickCreateView.propTypes = { +PostQuickCreate.propTypes = { onCancel: PropTypes.func.isRequired, onSave: PropTypes.func.isRequired, }; -const mapStateToProps = state => ({ - submitting: state.admin.loading > 0, -}); - -export default connect(mapStateToProps)(PostQuickCreateView); +export default PostQuickCreate; From 0555f095cc05c15a3033685279dd2fed2a44cb70 Mon Sep 17 00:00:00 2001 From: zyhou <richard.maxime9@gmail.com> Date: Sat, 25 May 2019 18:05:36 +0200 Subject: [PATCH 15/15] use makeStyles from material-ui core --- examples/simple/src/comments/CommentEdit.js | 2 +- examples/simple/src/comments/CommentList.js | 2 +- examples/simple/src/comments/PostQuickCreate.js | 8 ++++---- .../simple/src/comments/PostQuickCreateCancelButton.js | 2 +- examples/simple/src/comments/PostReferenceInput.js | 2 +- examples/simple/src/posts/PostList.js | 2 +- examples/simple/src/users/UserEdit.js | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/simple/src/comments/CommentEdit.js b/examples/simple/src/comments/CommentEdit.js index e4289e80d7c..6aeff5f4be3 100644 --- a/examples/simple/src/comments/CommentEdit.js +++ b/examples/simple/src/comments/CommentEdit.js @@ -1,6 +1,6 @@ import Card from '@material-ui/core/Card'; import Typography from '@material-ui/core/Typography'; -import { makeStyles } from '@material-ui/styles'; +import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { AutocompleteInput, diff --git a/examples/simple/src/comments/CommentList.js b/examples/simple/src/comments/CommentList.js index cd5383c736f..ad049c8a2ed 100644 --- a/examples/simple/src/comments/CommentList.js +++ b/examples/simple/src/comments/CommentList.js @@ -10,7 +10,7 @@ import CardContent from '@material-ui/core/CardContent'; import CardHeader from '@material-ui/core/CardHeader'; import Grid from '@material-ui/core/Grid'; import Toolbar from '@material-ui/core/Toolbar'; -import { makeStyles } from '@material-ui/styles'; +import { makeStyles } from '@material-ui/core/styles'; import { unparse as convertToCSV } from 'papaparse/papaparse.min'; import { DateField, diff --git a/examples/simple/src/comments/PostQuickCreate.js b/examples/simple/src/comments/PostQuickCreate.js index 94801a47a3e..fa7cea21f4d 100644 --- a/examples/simple/src/comments/PostQuickCreate.js +++ b/examples/simple/src/comments/PostQuickCreate.js @@ -1,7 +1,7 @@ import React, { useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; -import { connect, useSelector, useDispatch } from 'react-redux'; -import { makeStyles } from '@material-ui/styles'; +import { useSelector, useDispatch } from 'react-redux'; +import { makeStyles } from '@material-ui/core/styles'; import { CREATE, LongTextInput, @@ -57,7 +57,7 @@ const PostQuickCreate = ({ onCancel, onSave }) => { }, }); }, - [onSave] + [onSave], ); return ( @@ -74,7 +74,7 @@ const PostQuickCreate = ({ onCancel, onSave }) => { {...props} /> ), - [onCancel, submitting] + [onCancel, submitting], )} classes={{ form: classes.form }} > diff --git a/examples/simple/src/comments/PostQuickCreateCancelButton.js b/examples/simple/src/comments/PostQuickCreateCancelButton.js index 65911b6d48c..9fc96582223 100644 --- a/examples/simple/src/comments/PostQuickCreateCancelButton.js +++ b/examples/simple/src/comments/PostQuickCreateCancelButton.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import Button from '@material-ui/core/Button'; import IconCancel from '@material-ui/icons/Cancel'; -import { makeStyles } from '@material-ui/styles'; +import { makeStyles } from '@material-ui/core/styles'; import { useTranslate } from 'react-admin'; diff --git a/examples/simple/src/comments/PostReferenceInput.js b/examples/simple/src/comments/PostReferenceInput.js index 2c79011d48a..ce4a1122b06 100644 --- a/examples/simple/src/comments/PostReferenceInput.js +++ b/examples/simple/src/comments/PostReferenceInput.js @@ -2,7 +2,7 @@ import React, { Fragment, useState, useCallback, useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { Field } from 'redux-form'; -import { makeStyles } from '@material-ui/styles'; +import { makeStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; import DialogTitle from '@material-ui/core/DialogTitle'; diff --git a/examples/simple/src/posts/PostList.js b/examples/simple/src/posts/PostList.js index 574149aa852..dfa70b14c2b 100644 --- a/examples/simple/src/posts/PostList.js +++ b/examples/simple/src/posts/PostList.js @@ -1,6 +1,6 @@ import BookIcon from '@material-ui/icons/Book'; import Chip from '@material-ui/core/Chip'; -import { makeStyles } from '@material-ui/styles'; +import { makeStyles } from '@material-ui/core/styles'; import React, { Children, Fragment, cloneElement } from 'react'; import { BooleanField, diff --git a/examples/simple/src/users/UserEdit.js b/examples/simple/src/users/UserEdit.js index 9b99a1d9e5c..588c5e39dfa 100644 --- a/examples/simple/src/users/UserEdit.js +++ b/examples/simple/src/users/UserEdit.js @@ -13,7 +13,7 @@ import { Toolbar, required, } from 'react-admin'; -import { makeStyles } from '@material-ui/styles'; +import { makeStyles } from '@material-ui/core/styles'; import UserTitle from './UserTitle'; import Aside from './Aside';