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:
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.
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:
Now, let’s see how barrel exports actually work.
To use barrel exports, here’s what we need to do:
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 fileLet’s walk through a simple example so that we can see how this works.
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: layout
, modals
, and utilities
.
In the layout
folder, we have three layout component files: Aside.js
, Footer.js
, and NavBar.js
. In the utilities
folder we have five files; Alert.js
, Loader.js
, SnackBar.js
, Success.js
, and Button.js
.
Here’s the 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.
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:
Let’s see this action:
The above file tree shows our components
folder and subfolders: layout
, modals
, 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';
Now, we can export the subfolder files in our main barrel using an alias (util
, mod
, and lay
) for each sub-barrel:
export * as util from './utilities' export * as mod from './modals' export * as lay from './layout'
Now, we can import the subfolder files using their individual alias (util
, mod
, 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> ); }
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.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.