Using barrel exports to organize React components
Friday 08 July 2022 12:12 PM Beirut Time · 263
Wajdi Alkayal Wajdi Alkayal
Using barrel exports to organize React components

A common task when developing React applications is the act of bringing components or modules from different files into the parts of the application where they are needed. You may find that you often have to dig deep into your folder structure just to import a single React module.

Now, imagine having to do the same thing for multiple modules. This would be very tedious and would also make our codebase a bit messy, which nobody likes!

In this article, we’ll introduce the concept of barrel exports in React, and we’ll discuss how to use barrel exports to save development time and improve collaboration and efficiency. We’ll even look at an advanced use case for when you want to use multiple aliases on a single import statement.

Jump ahead:

What are barrel exports?

A barrel enables us to consolidate, or roll up, exports from multiple files or modules into one single module. Barrels streamline imports, simplify exports, and help us avoid a lot of clutter in our codebase.

Let’s look at how barrels can simplify imports, both mentally and visually.

This code shows how we’d typically handle imports in our React application:

import Button from '../../components/utilities/Button.js';
import Alert from '../../components/utilities/Alert.js';
import SnackBar from '../../components/utilities/SnackBar.js'
import Loader from '../../components/utilities/Loader.js'
import Success from '../../components/utilities/Success.js'

These are just five import statements, but imagine if we needed more components, we’d have even more lines of code.

Now, here’s how the code looks if we use barrel exports to handle the same five imports:

import { Button, Alert, SnackBar, Loader, Success  } from '../../components';

We can make the code even cleaner by aliasing everything, so whenever we need a component we just prefix the alias with the React component name, like so:

import * as com from '../../components';

Here’s how we use it:

const Home=()=>{
    return(
        <div className="home">
            //aliasing our imports
            <com.Button />
        </div>
    )
}

Our local imports are cleaner and easier on the eyes, and it doesn’t take much mental effort to remember where we’re importing from because it’s all from one folder.

Isn’t this exciting? let’s take a look at some additional benefits of working with barrel exports.

Benefits of barrel exports

Barrel exports are not just about looks. They do more than keep our codebase clean.

One of the most significant advantages of barrel exports is collaboration. Consider working on an application where multiple teams use a shared UI component. A change to the project structure could break a large number of imports in the application.

We don’t have to worry about this with barrel exports. We can change the location of React components without having to refactor our import statements.

Here are some of the benefits you get when you load multiple exports into one barrel:

  • Improved component auto-importing
  • The ability to organize the application folder as we see fit
  • Improved IntelliSense
  • Single source of truth for all exports defined in the barrel

Now, let’s see how barrel exports actually work.

How to use barrel exports

To use barrel exports, here’s what we need to do:

  1. Change from default exports to named exports, when exporting React components or modules
  2. Add an index.js file to any directory we want to barrel from (this will effectively become our barrel; we’ll re-export all of our components from this file

Let’s walk through a simple example so that we can see how this works.

Folder Structure

The above file tree helps us visualize our folder structure. At the root of the components folder, we have an index.js file, which will be our barrel. The components folder also has three nested folders: layoutmodals, and utilities.

In the layout folder, we have three layout component files: Aside.jsFooter.js, and NavBar.js. In the utilities folder we have five files; Alert.jsLoader.jsSnackBar.jsSuccess.js, and Button.js.

Here’s the full file tree:

Full File Tree

To access a React component with barrel exports and use it across our application, we simply use named exports to export the component.

Here’s an example using named exports with the Alert.js file:

export const Alert=()=>{
    return<h1>Alert</h1>
}

Now that’s all set up, we can export all the components in a barrel. In the index.js file, at the root of the components folder, we can export all the components using the following commands:

export { Alert } from './utilities/Alerts';
export { Button } from './utilities/Button';
export { Loader } from './utilities/Loader';
export {SnackBar} from './utilities/SnackBar';
export { Success } from './utilities/Success';

In the above code, we’re only exporting components from the utilities folder.

Now, we can simply use the components, like so:

import * as util from './components'
function App() {
  return (
    <div className="App">
      <h1>Hello World</h1>
      <util.Button />
      <util.Loader />
      <util.Alert />
      <util.SnackBar />
      <util.Success />
    </div>
  );
}

Consider the following scenario: team A and team B are both collaborating on our application. Team A is reorganizing the application and has moved the Button.js file to a different folder located elsewhere in the application.

What do you think will happen to our React application? If you said: “It will break”, you’re correct. Why? Because our barrel is no longer aware of the Button.js file’s path.

Fortunately, team A can easily fix this issue. Our barrel serves as a single source of truth for all exports defined in it, so team A simply needs to update the Button.js file path in our barrel, and every component that uses it will regain access. There will be no need to manually update the path for each file.

Advanced use case: multiple aliases

Now, let’s take our learning a step further. In the previous example, we had just one barrel file in the components folder handling all of the exports from the utilities folder, and we imported the components using the util alias.

That was pretty neat, but don’t forget we also have a layout folder and a modals folder in our components folder. We can’t import their respective components using the same util alias, because that would be confusing.

Here’s how we can have multiple aliases from one central barrel file:

  1. Ensure each components folder has its own barrel
  2. Export using an alias in the main barrel file
  3. Import using each individual alias

Let’s see this action:

Each folder has its own barrel

Components Folders and Subfolders

The above file tree shows our components folder and subfolders: layoutmodals, and utilities. Each subfolder now has its own barrel, or index.js file.

Here’s what the code looks like:

//layouts barrel
export { Aside } from "./Aside";
export { Footer } from "./Footer";
export { NavBar } from "./NavBar";

//modals barrel
export {Failure} from './Failure';
export {Success} from './Success';

//utilities barrel
export { Alert } from './Alerts';
export { Button } from './Button';
export { Loader } from './Loader';
export {SnackBar} from './SnackBar';
export { Success } from './Success';

Export using an alias in the main barrel file

Now, we can export the subfolder files in our main barrel using an alias (utilmod, and lay) for each sub-barrel:

export * as util from './utilities'
export * as mod from './modals'
export * as lay from './layout'

Import using each individual alias

Now, we can import the subfolder files using their individual alias (utilmod, and lay):

import {util, mod, lay} from './components'

Components from the utilities folder will have the util prefix, while components from the modals and layout folders will have the mod and lay prefixes, respectively.

Here’s what the code looks like:

>import {util, mod, lay} from './components'
function App() {
  return (
    <div className="App">
      <h1>Hello World</h1>
        //Utilities
      <util.Button />
      <util.Loader />
      <util.Alert />
      <util.SnackBar />
      <util.Success />

      //modals
      <mod.Failure />
      <mod.Success />

      //layouts
      <lay.Aside />
      <lay.Footer />
      <lay.NavBar />
    </div>
  );
}

Conclusion

A well-architected React application is easier to design, deploy, maintain, and scale. Barrel exports help by enabling us to clean up our local imports, resulting in a cleaner codebase, better collaboration, and enhanced organization.

Related Posts
Graphic design
09 June
The Power of Email Marketing
03 June
Photography
01 June