React Native ⚛️ is a powerful framework for building cross-platform mobile apps, but as projects grow, maintaining code quality, scalability, and collaboration becomes challenging. In this guide, we’ll explore tools and strategies to elevate your React Native codebase, including Prettier, TypeScript, ESLint, module resolvers, and more.

✨ 1. Code Formatting with Prettier

Consistent code formatting improves readability and reduces merge conflicts. Prettier automates this process by enforcing a uniform style across your codebase.

🔧 Setup:

  1. Install dependencies:
npm install --save-dev prettier
  1. Create a .prettierrc configuration file:
{
     "semi": true,
     "singleQuote": true,
     "trailingComma": "all",
     "printWidth": 80
   }
  1. Add a script to your package.json:
"scripts": {
     "format": "prettier --write \"**/*.{js,jsx,ts,tsx}\""
   }
  1. Run the following command to format all files:
npm run format

💡 Pro Tip: Integrate Prettier with your IDE for real-time formatting.


🔒 2. Type Safety with TypeScript

TypeScript catches errors at compile time, provides better autocompletion, and makes refactoring safer.

🚀 Migration Steps:

  1. Install TypeScript and necessary types:
npm install --save-dev typescript @types/react @types/react-native
  1. Create a tsconfig.json:
{
     "compilerOptions": {
       "allowJs": true,
       "esModuleInterop": true,
       "jsx": "react-native",
       "lib": ["esnext"],
       "moduleResolution": "node",
       "strict": true,
       "baseUrl": "./src",
       "paths": {
         "@components/*": ["components/*"]
       }
     },
     "exclude": ["node_modules"]
   }
  1. Rename .js files to .tsx incrementally and fix type errors.

📌 Example: Typed Component

interface ButtonProps {
  title: "string;"
  onPress: () => void;
}

const Button = ({ title, onPress }: ButtonProps) => (
  <TouchableOpacity onPress={onPress}>
    <Text>{title}</Text>
  </TouchableOpacity>
);

🚨 3. Linting with ESLint

ESLint identifies problematic patterns in your code. For TypeScript projects, combine it with @typescript-eslint.

🛠️ Configuration:

  1. Install dependencies:
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react eslint-plugin-react-native
  1. Create .eslintrc.js:
module.exports = {
     root: true,
     extends: [
       'eslint:recommended',
       'plugin:@typescript-eslint/recommended',
       'plugin:react/recommended',
       'plugin:react-native/all',
     ],
     parser: '@typescript-eslint/parser',
     plugins: ['@typescript-eslint', 'react', 'react-native'],
     rules: {
       'react-native/no-raw-text': 'off',
       '@typescript-eslint/no-explicit-any': 'warn',
     },
     settings: {
       react: { version: 'detect' },
     },
   };
  1. Add a lint script:
"scripts": {
     "lint": "eslint \"**/*.{js,jsx,ts,tsx}\""
   }

🏗️ 4. Clean Imports with Module Resolver

Avoid messy relative paths like ../../../components/Button using babel-plugin-module-resolver.

🔧 Setup:

  1. Install the plugin:
npm install --save-dev babel-plugin-module-resolver
  1. Update babel.config.js:
module.exports = {
     plugins: [
       [
         'module-resolver',
         {
           root: ['./src'],
           alias: {
             '@components': './src/components',
             '@utils': './src/utils',
           },
         },
       ],
     ],
   };
  1. Update tsconfig.json:
{
     "compilerOptions": {
       "baseUrl": "./src",
       "paths": {
         "@components/*": ["components/*"],
         "@utils/*": ["utils/*"]
       }
     }
   }
  1. Use clean imports:
import Button from '@components/Button';

🤖 5. Automate Workflows with Git Hooks

Enforce code quality pre-commit with Husky and lint-staged.

🚀 Setup:

  1. Install dependencies:
npm install --save-dev husky lint-staged
  1. Configure Husky in package.json:
"scripts": {
     "prepare": "husky install"
   },
   "lint-staged": {
     "**/*.{js,jsx,ts,tsx}": [
       "eslint --fix",
       "prettier --write",
       "git add"
     ]
   }
  1. Create a pre-commit hook:
npx husky add .husky/pre-commit "npx lint-staged"

🏆 Additional Best Practices

📁 A. Directory Structure

Organize files by feature or domain:

assets/
src/
  ├── components/
  ├── screens/
  ├── utils/
  ├── hooks/
  └── store/

🧪 B. Testing

Add Jest for unit tests and Detox for E2E testing:

npm install --save-dev jest @testing-library/react-native detox

🔥 C. Monitoring

Integrate tools like Sentry or Firebase Crashlytics to track runtime errors.


🎯 Conclusion

By integrating these tools and best practices, your React Native codebase becomes:
Consistent with Prettier

Type-safe with TypeScript

Error-resistant with ESLint

Maintainable with module resolvers

Automated via Git hooks

Start incrementally—even small improvements can yield immediate benefits. Over time, these changes will reduce technical debt, streamline collaboration, and make your app more robust. Happy coding! 🚀