Clean Code: Keep Your Imports Tidy

The import statements at the top of a file are like the table of contents for that file. They tell you what dependencies the module has and where they come from. When this list is long and disorganized, it can be a bit of a nightmare to navigate. Keeping your imports clean is a simple way to improve the readability of your code.

Let's look at an exaggerated, but not entirely unrealistic, example.

// Bad: A chaotic, long list of imports
import React, { useState, useEffect, useCallback, useMemo, useContext } from 'react';
import { Button, Card, Modal, Dropdown, Tooltip, Badge, Avatar, Icon, Spinner, Alert, Form, Input, Select, Checkbox, Radio, Switch, Slider, DatePicker, TimePicker, Upload, Progress, Steps, Tabs, Menu, Breadcrumb, Pagination, Table, List, Tree, Transfer, Cascader, AutoComplete, Mentions, Rate, Divider, Space, Row, Col, Layout, Header, Footer, Sider, Content, Affix, BackTop, Anchor, ConfigProvider, LocaleProvider, ThemeProvider } from 'antd';
import { useRouter, useParams, useLocation, useHistory, useMatch, useNavigate } from 'react-router-dom';
import { useSelector, useDispatch, connect, Provider, createStore, applyMiddleware, combineReducers, bindActionCreators } from 'react-redux';
import { createSlice, configureStore, getDefaultMiddleware, createAsyncThunk, createEntityAdapter, createSelector } from '@reduxjs/toolkit';

// Good: Organized and grouped imports make it easy to see what's being used.
import React, { useState, useEffect } from 'react';
import { useRouter, useParams } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';

// UI Components
import { Button, Card, Modal, Form, Input } from 'antd';

// Types and utilities
import type { User, Product } from '@/types';
import { formatCurrency, validateEmail } from '@/utils';

A Simple System for Organization

A good practice is to group your imports and add a little space between the groups. A common way to order them is:

  1. Built-in modules (e.g. fs, path in Node.js)
  2. External libraries (e.g. react, lodash)
  3. Internal modules (e.g. components, services from your own codebase)

You can further separate your internal modules using absolute paths from those using relative paths.

// 1. External libraries
import React from 'react';
import { useRouter } from 'next/router';
import { useQuery } from 'react-query';


// 2. Internal modules (absolute imports)
import { Button } from '@/components/Button';
import { userService } from '@/services/userService';
import type { User } from '@/types/user';

// 3. Relative imports
import { ProductCard } from './ProductCard';
import { useProductData } from './hooks/useProductData';

Quick Tips

  • Group your imports. This makes it easy to scan the dependencies of a file.
  • Use barrel exports (index.ts files) with caution. They can be great for reducing the number of import statements, but they can also lead to larger bundle sizes if not used carefully and can sometimes make it harder to see where things are coming from.
  • Automate it! Use a tool like the ESLint import/order rule to enforce a consistent order automatically.

Tidy imports might seem like a small thing, but they contribute to a codebase that is clean, professional, and easy for anyone to jump into.