-
-
Notifications
You must be signed in to change notification settings - Fork 32.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
[material-ui][ListItem] Removing deprecated props #41566
Conversation
Netlify deploy previewListItem: parsed: -19.53% 😍, gzip: -17.97% 😍 Bundle size reportDetails of bundle changes (Toolpad) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @thathva, thanks for working on this, here's my initial review.
Besides the comments, we should add these removals as breaking changes in https://github.com/DiegoAndai/material-ui/blob/next/docs/data/material/migration/migration-v5/migration-v5.md. You might have to rebase/merge next
into your branch.
I have made the changes as commented. Let me know if there are any more changes! |
Nicely done @thathva! Regarding the migration guide: We need to add these removals to the guide in this PR. But the guide was added after the
Which will bring the latest changes of the |
Thank you for the references and the detailed steps @DiegoAndai! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @thathva, thanks for incorporating the suggested changes 🙌🏼
I left a suggestion on the migration guide structure and text.
Besides that, I think we should add a codemod for this breaking change in this same PR. The codemod will replace all occurrences of <ListItem button />
to <ListItemButton />
. Would you be willing to work on it? If so, I can set it up and guide you through it.
Hi @DiegoAndai |
I'll set it up today/tomorrow and reach out 😊 |
Hey @thathva, I set up the codemods for v6 🎉 First you'll have to merge
Then, read the codemods contributing guide. The codemod we will add should be named
The codemod should be added to the For further guidance, I recommend going through:
Please reach out if you're stuck and need help 😊 I will be on vacation starting tomorrow (March 28th) until April 8th, so I won't attend to notifications during that time. @siriwatknp may I ask you to provide guidance in the meantime? |
Awesome, thanks for the guide @DiegoAndai! |
Hey @siriwatknp
import findComponentJSX from '../../util/findComponentJSX';
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api, options) {
const j = api.jscodeshift;
const root = j(file.source);
const printOptions = options.printOptions;
//Rename components that have ListItem button to ListItemButton
findComponentJSX(j, { root, componentName: 'ListItem' }, (elementPath) => {
const index = elementPath.node.openingElement.attributes.findIndex(
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'button',
);
if (index !== -1) {
elementPath.node.openingElement.name.name = 'ListItemButton';
elementPath.node.openingElement.attributes.splice(index, 1);
}
});
//Find if there are ListItem imports/named imports.
let containsListItemImport = root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material');
let containsListItemNamedImport = containsListItemImport.find(j.ImportSpecifier).filter(path => path.node.imported.name === 'ListItem');
let containsListItem = false;
//Find components that use ListItem. If they do, we shouldn't remove it
findComponentJSX(j, { root, componentName: 'ListItem' }, (elementPath) => {
if(elementPath.node.openingElement.name.name === 'ListItem') {
containsListItem = true;
}
});
//Remove ListItem import if there is no usage
if(containsListItemNamedImport.length === 0 || !containsListItem) {
root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material/ListItem').remove();
}
//If ListItemButton does not already exist, add it at the end
let imports = root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material/ListItemButton');
if(imports.length === 0) {
let lastImport = root.find(j.ImportDeclaration).at(-1);
// Insert the import for 'ListItemButton' after the last import declaration
lastImport.insertAfter(
j.importDeclaration(
[j.importDefaultSpecifier(j.identifier('ListItemButton'))],
j.stringLiteral('@mui/material/ListItemButton')
)
);
}
return root.toSource(printOptions);
}
import ListItem from '@mui/material/ListItem';
import {ListItem as MyListItem} from '@mui/material';
<ListItem button/>;
<MyListItem button/>;
import ListItemButton from '@mui/material/ListItem';
import {ListItemButton as MyListItemButton} from '@mui/material';
<ListItemButton />;
<MyListItemButton />; The test case to transform the props is failing with these results: +expected
-actual
-import {ListItem as MyListItem} from '@mui/material';
-
-import ListItemButton from "@mui/material/ListItemButton";
-
-
-
-<ListItemButton />;
-
-
-
-<ListItemButton />;
+import {ListItemButton as MyListItemButton} from '@mui/material';
+import ListItemButton from '@mui/material/ListItem';
+
+<ListItemButton />;
+<MyListItemButton />; |
Hey @thathva, I'm back from vacation so I can help with this.
Could you commit this first version? That way it will be easier to review. In the following code: //Remove ListItem import if there is no usage
if(containsListItemNamedImport.length === 0 || !containsListItem) {
root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material/ListItem').remove();
} We're only removing the
is not removed. We have to cover that case as well. |
Hey @DiegoAndai |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @thathva! Here are some suggestions to move forward
//Find if there are ListItem imports/named imports. | ||
let containsListItemImport = root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material'); | ||
let containsListItemNamedImport = containsListItemImport.find(j.ImportSpecifier).filter(path => path.node.imported.name === 'ListItem'); | ||
let containsListItem = false; | ||
|
||
//Find components that use ListItem. If they do, we shouldn't remove it | ||
findComponentJSX(j, { root, componentName: 'ListItem' }, (elementPath) => { | ||
if(elementPath.node.openingElement.name.name === 'ListItem') { | ||
containsListItem = true; | ||
} | ||
}); | ||
|
||
//Remove ListItem import if there is no usage | ||
if(containsListItemNamedImport.length === 0 || !containsListItem) { | ||
// root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material').find(j.ImportSpecifier) | ||
// .filter(path => path.node.imported.name === 'ListItem').remove(); | ||
root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material/ListItem').remove(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's try this (I haven't tried it so it might need some fixing):
//Find if there are ListItem imports/named imports. | |
let containsListItemImport = root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material'); | |
let containsListItemNamedImport = containsListItemImport.find(j.ImportSpecifier).filter(path => path.node.imported.name === 'ListItem'); | |
let containsListItem = false; | |
//Find components that use ListItem. If they do, we shouldn't remove it | |
findComponentJSX(j, { root, componentName: 'ListItem' }, (elementPath) => { | |
if(elementPath.node.openingElement.name.name === 'ListItem') { | |
containsListItem = true; | |
} | |
}); | |
//Remove ListItem import if there is no usage | |
if(containsListItemNamedImport.length === 0 || !containsListItem) { | |
// root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material').find(j.ImportSpecifier) | |
// .filter(path => path.node.imported.name === 'ListItem').remove(); | |
root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material/ListItem').remove(); | |
} | |
//Find components that use ListItem. If they do, we shouldn't remove it | |
findComponentJSX(j, { root, componentName: 'ListItem' }, (elementPath) => { | |
if(elementPath.node.openingElement.name.name === 'ListItem') { | |
containsListItem = true; | |
} | |
}); | |
//Find if there are ListItem imports/named imports. | |
let containsListItemImport = root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material'); | |
let containsListItemNamedImport = containsListItemImport.find(j.ImportSpecifier).filter(path => path.node.imported.name === 'ListItem'); | |
let containsListItem = false; | |
// Remove ListItem imports if there is no usage | |
if(!containsListItem) { | |
// Remove named imports | |
root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material').find(j.ImportSpecifier).filter(path => path.node.imported.name === 'ListItem').remove(); | |
// Remove default imports | |
root.find(j.ImportDeclaration).filter(path => path.node.source.value === '@mui/material/ListItem').remove(); | |
} |
* @param {import('jscodeshift').API} api | ||
*/ | ||
export default function deprecationsAll(file, api, options) { | ||
file.source = transformerListItemButtonProps(file, api, options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be added to the v6-all
one, as it's not a deprecation. And we should remove this file.
Hey @DiegoAndai!
|
@@ -0,0 +1,21 @@ | |||
fn({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DiegoAndai , I am not sure about these transformations honestly, as there could be different interpretation on what was the intention. I did what felt most intuitive to me, but I am honestly not happy with it. I think I would rather not handle this and let people do what they think should be best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, the logic is: If MuiListItem
is present and has button
as default prop, then remove button
and create a MuiListItemButton
entry copying the other default prop values, right? That is the most likely migration to me.
What other interpretations of the intention are you thinking about?
@DiegoAndai I improved a lot the codemod in regards to the replacement of the open tags & removing the non-used imports. I am not sure about the theming codemod, honestly I would just drop that logic. I am letting you do the final review. |
docs/data/material/migration/migrating-to-v6/migrating-to-v6.md
Outdated
Show resolved
Hide resolved
Signed-off-by: Marija Najdova <mnajdova@gmail.com>
'li' | ||
> | ||
>; | ||
declare const ListItem: OverridableComponent<ListItemTypeMap<{}, 'li'>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Co-authored-by: Siriwat K <siriwatkunaporn@gmail.com> Signed-off-by: Marija Najdova <mnajdova@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the codemod, I could not think of other edge cases and I would not worry about it that much. It should not block the migration.
docs/data/material/migration/migrating-to-v6/migrating-to-v6.md
Outdated
Show resolved
Hide resolved
Signed-off-by: Marija Najdova <mnajdova@gmail.com>
@thathva thanks for kicking off this effort. I pushed few commits and merged it :) |
Thank you so much @mnajdova and I apologize for not finishing it completely. The changes you made looks great! |
BREAKING CHANGES
ListItem
's propsautoFocus
,button
,disabled
, andselected
, deprecated in v5, have been removed. To replace thebutton
prop, useListItemButton
instead. The other removed props are available in theListItemButton
component as well.Use this codemod to migrate your project to the
ListItemButton
component:As the
ListItem
no longer supports these props, the class names related to these props were removed. You should use thelistItemButtonClasses
object instead.