Importing React components using destructuring in Javascript

February 02, 2021

How did this come about?

Recently I have been using Material UI, and I really like the way I could pull in components through destructuring assignment in Javascript:

import { Card, CardContent, Container, Grid, Typography } from "@material-ui/core"

The way I would do this in the past

Typically, in the past, I would probably export my component like this from the actual component file:

// src/components/Artist/ArtistListItem.js

import React from "react"

const ArtistListItem = () => {
  return (
    // JSX
  )
}

export default ArtistListItem

This would allow me to import that component like this within one of my Next.js pages:

// src/pages/spotify.js

import ArtistListItem from "../components/Artist/ArtistListItem

This really isn't too bad when getting an app up and running, but if I am importing in even just a half dozen components, the import section of my file quickly gets a little overwhelming:

// src/pages/spotify.js

import ArtistList from "../components/Artist/ArtistList"
import ArtistListItem from "../components/Artist/ArtistListItem"
import ArtistAvatar from "../components/Artist/ArtistAvatar"
import PageHeading from "../components/Page/PageHeading"
import PageSubheading from "../components/Page/PageSubheading"
import PageSidebar from "../components/Page/PageSidebar"
import PageFooter from "../components/Page/PageFooter"

If the import sections of your pages start to look like this, you could maybe benefit from a refactor of your imports using destructuring assignment.

Cleaning it up with destructuring

My desired outcome

Looking at the above example, let's take a look at the the end-result I would actually like to achieve:

// src/pages/spotify.js

import { ArtistList, ArtistListItem, ArtistAvatar } from "../components/Artist"

Leveraging exports within our index files

The magic here really lies within index.js files that I will place throughout our file structure. Using the above example, I can place an index.js file within my Artist directory that will export out the artist-related components, making them available to destructuring assignment.

My folder structure might then look like this:

├── src
│   └── components
│       └──  Artist
│           ├── ArtistList.js
│           ├── ArtistListItem.js
│           ├── ArtistAvatar.js
│           └── index.js

Now, just to take a quick look at that component file from earlier:

// src/components/Artist/ArtistListItem.js

import React from "react"

const ArtistListItem = () => {
  return (
    // JSX
  )
}

// Note the default getting exported out here
export default ArtistListItem

Now within my newly-added index.js I can give access to the ArtistListItem component during restructuring like this:

// src/components/Artist/index.js

// Import the default from each component value, and rename here if needed
import { default as ArtistList } from "./ArtistList"
import { default as ArtistListItem } from "./ArtistListItem"
import { default as ArtistAvatar } from "./ArtistAvatar"

// I export out the components from this file
export default {
  ArtistList,
  ArtistListItem,
  ArtistAvatar
}

Finally, I should be able to pull them in as desired within my page component:

// src/pages/spotify.js

import { ArtistList, ArtistListItem, ArtistAvatar } from "../components/Artist"

Taking it further

Destructuring any component from my components directory

While what I have now is much better, as it stands now, if I were to pull in Page components, there would be redundancy again within our imports:

// src/pages/spotify.js

import { ArtistList, ArtistListItem, ArtistAvatar } from "../components/Artist"
import { PageHeading, PageSubheading, PageSidebar, PageFooter } from "../components/Page"

It would be ideal I think to be able to simply pull in any component from the components directory. Again, just as before, the magic here would be adding another index.js file to the components directory:

├── src
│   └── components
│       ├── Artist
│       │   ├── ArtistList.js
│       │   ├── ArtistListItem.js
│       │   ├── ArtistAvatar.js
│       │   └── index.js
│       └── Page
│       │   ├── PageHeading.js
│       │   ├── PageSubheading.js
│       │   ├── PageSidebar.js
│       │   ├── PageFooter.js
│       │   └── index.js
│       └── index.js // Add this here

Within that main index.js in our components directory, similarly to how I made the individual components available to be destructured within their respective index.js files, I am going to do the same thing within src/components/index.js:

// src/components/index.js

import { ArtistList, ArtistListItem, ArtistAvatar } from "./Artist"
import { PageHeading, PageSubheading, PageSidebar, PageFooter } from "./Page"

export default {
  ArtistList,
  ArtistListItem,
  ArtistAvatar
  PageHeading,
  PageSubheading,
  PageSidebar,
  PageFooter
}

Finally, we should be able to pull in any component by simply destructuring an import of the components directory:

// src/pages/spotify.js

import {
  ArtistList,
  ArtistListItem,
  ArtistAvatar
  PageHeading,
  PageSubheading,
  PageSidebar,
  PageFooter
} from "../components"

Join my mailing list to stay updated with web development news.

About the Author

Jed Darrohn is a software developer that specializes in Laravel, Vue.js, and React. He lives in Denver, Colorado with his Australian Shepherd, Bessie.

© 2021 Jed Darrohn

Sitemap