Using @ alias in React for cleaner React and TypeScript imports from various paths

React along with TypeScript is a wonderful tool for building scalable, maintainable, modern web applications. React + TypeScript is very popular among developers. In this post we will see the use of Aliases in React+TypeScript+Vite(optional).

To follow along with this tutorial, you’ll need basic knowledge of React, JavaScript and some familiarity with TypeScript. To test it, you should have an existing React App running.

Why to use @ alias in React?

In order to import a Button component from same folder or path we will right it as:

import { Button } from './button';

To import the Button component from a sibling of the parent folder we will write it as:

import { Button } from '../components/button';

And at some point it will go like:

import { Button } from '../../../../components/button';

You see how messy the last statement above has become! @ alias is a workaround to this.

As a React project grows in size and complexity, import statements can become tedious. In particular, the default relative path imports can quickly become long and hinder code readability.

So what is the solution to this? Short answer is, to configure one or more path aliases.

How to use @ alias in react?

In this article, we will explore how to leverage path aliases to enhance the organization and maintainability of your React and TypeScript projects.

Understanding import statements in React and TypeScript apps

In React and TypeScript apps, developers use import statements to bring in functionality from other modules or files. This practice ensures we develop software that is reusable and modular.

Although import statements are useful in this way, they can lead to problems when they aren’t used properly. The code snippet below shows a typical example of this problem:

import React from 'react';
import { Button } from '../../../../components/button'; // this is so unpredictable

function SomeComponent() {
  return <Button />;
};

As you can see, this code snippet uses relative imports from the current file to import the Button component. However, this import pattern is messy because it’s importing the component from a deeply nested directory.

It may be okay for relatively small projects, but as the project grows, typing and reading long import paths becomes tedious. It may also be slow to load as your app has to search for files, rather than just importing them!

How path aliases can help simplify import statements

Path aliases let developers define custom shortcuts for import paths, making them cleaner and more intuitive. With path aliases set up, you can have clean and concise imports regardless of the size of the project, as shown in the code snippet below:

import React from 'react';
import { Button } from '@components/button'; // clean and concise import :)

function SomeComponent() {
  return <Button />;
};

By setting up path aliases in a React and TypeScript app, you can simplify import statements, improve code navigation, and enhance the overall development experience.

Configuring path aliases in the tsconfig.json OR tsconfig.app.json file

You can configure path aliases easily in your project’s tsconfig.json OR tsconfig.app.json file if it exists. tsconfig.app.json takes a precedence. These files are usually found at the root of a TypeScript project.

To configure your path aliases in this file, simply add a paths property in the compilerOptions object. Then, you can map path alias names to file paths as shown in the code snippet below:

{
  "compilerOptions": {
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  }
}

The above code tells the TypeScript compiler to resolve imports from the @/* alias to the ./src/* directory. Once you set up the path alias, you can use it in your import statements.

For example, you can import a Button component in the src/components directory directly from anywhere in the project like this:

import { Button } from "@/components/Button"; 

function App() { 
  return ( <Button>Click Me</Button> )
}

Without a path alias set up, importing the Button component from another file — for example, src/pages/dashboard/profile/settings/index.tsx — would look something like this:

import { Button } from '../../../../components/Button';

function Settings() {
  return (
    <Button>Click Me</Button>
  )
}

You can take this a step further and add more path aliases, which can be beneficial for large projects that store critical parts of the app in well-defined directories. In the tsconfig.app.json file, update the paths field as shown in the following code snippet:

{
  "compilerOptions": {
    "baseUrl" : "./src",
    "paths": {
      "@components/*": ["./components/*"],
      "@ui/*": ["./components/common/ui/*"],
      "@pages/*": ["./pages/*"],
      "@hooks/*": ["./hooks/*"],
      "@api/*": ["./api/*"],
      "@utils/*": ["./utils/*"],
    }
  }
}

The baseUrl field in the code snippet above is used to make the path aliases shorter to write.

Using Vite? Edit the vite.config.ts

import path from 'path';

...

export default defineConfig({
  ...
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
})

You can add more alias as you did in the tsconfig.app.json file above.

There is a plugin which can compile paths defined in the tsconfig.json or tsconfig.app.json and insert them into the defineConfig module of vite. Install this module if you want to save yourself from updating two files each time you add new alias to vite or tsconfig configuration file.

Install vite-tsconfig-paths plugin (optional)

npm install vite-tsconfig-paths

Update vite.config.ts

import tsconfigPaths from 'vite-tsconfig-paths'

And add to plugins

export default defineConfig({
  plugins: [
    react(),
    ....other plugins
    tsconfigPaths()
  ]
})

After adding and setting this plugin next time you have to add new alias in the tsconfig.json or tsconfig.app.json file only.

Leave a Reply