reactjstypescriptmaterial-uijscodeshiftcodemod

jscodeshift to convert all named imports to default import MUI V5


Can somebody help with a jscodeshift to convert all the named imports to default import for MUI V5 (React + Typescript) Current code

import { Button, TextField } from '@mui/material';

Expected output

import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';

Solution

  • I whipped this up using Codemod Studio (codemod share link):

    The link simply shows the codemod I placed below. Feel free to access it in the studio if you want to test or edit the codemod.

    This should do what you are looking for.

    I haven't tested it outside of codemod studio, so make sure you do so. To easily deploy it, you can export it to Intuita VS Code Extension in the top right corner (as shown here @2:06).

    You can also run the codemod using jscodeshift cli as usual, but I find the extension to be easier for me.

    import type { FileInfo, API, Options } from 'jscodeshift';
    export default function transform(
        file: FileInfo,
        api: API,
        options: Options,
    ): string | undefined {
        const j = api.jscodeshift;
        const root = j(file.source);
    
        // Find all ImportDeclaration nodes
        root.find(j.ImportDeclaration).forEach(path => {
            // Ensure the import source is '@mui/material'
            if (path.node.source.value === '@mui/material') {
                // Ensure the import specifiers are ImportSpecifier nodes
                if (path.node.specifiers.every(specifier => specifier.type === 'ImportSpecifier')) {
                    // Create new ImportDeclaration nodes for each ImportSpecifier
                    const newImports = path.node.specifiers.map(specifier => {
                        // Ensure the imported element is an Identifier
                        if (specifier.imported.type === 'Identifier') {
                            // Create a new ImportDeclaration node
                            return j.importDeclaration(
                                [j.importDefaultSpecifier(j.identifier(specifier.imported.name))],
                                j.literal(`@mui/material/${specifier.imported.name}`)
                            );
                        }
                    });
    
                    // Replace the original ImportDeclaration node with the new ones
                    path.replace(...newImports);
                }
            }
        });
    
        return root.toSource();
    }
    

    By looking at the exported code, the codemod simply looks for the @mui/material import source and replaces it with the imports you need.

    You can create and debug simple codemods like this using Codemod Studio. See here how to create your own codemods. Also, you can create them natively using jscodeshift API, but I find this method to be easier.

    You can simply insert the before code snippet in the 'Before' pane, the after code snippet in the 'After' pane, run ModGPT, and test/debug the returned codemod.

    Disclosure: I'm affiliated with Intuita. By no means this is self-promotion. This is how I create codemods for simple use cases like this. Not all codemods can be made with Codemod Studio at the current time, but it can go a long way for simple changes and refactors like this.