DEV Community

Suman Bhattarai
Suman Bhattarai

Posted on

🚀 Enhancing Your React Native Codebase: Best Practices & Modern Tooling

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
Enter fullscreen mode Exit fullscreen mode
  1. Create a .prettierrc configuration file:
   {
     "semi": true,
     "singleQuote": true,
     "trailingComma": "all",
     "printWidth": 80
   }
Enter fullscreen mode Exit fullscreen mode
  1. Add a script to your package.json:
   "scripts": {
     "format": "prettier --write \"**/*.{js,jsx,ts,tsx}\""
   }
Enter fullscreen mode Exit fullscreen mode
  1. Run the following command to format all files:
   npm run format
Enter fullscreen mode Exit fullscreen mode

💡 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
Enter fullscreen mode Exit fullscreen mode
  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"]
   }
Enter fullscreen mode Exit fullscreen mode
  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>
);
Enter fullscreen mode Exit fullscreen mode

🚨 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
Enter fullscreen mode Exit fullscreen mode
  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' },
     },
   };
Enter fullscreen mode Exit fullscreen mode
  1. Add a lint script:
   "scripts": {
     "lint": "eslint \"**/*.{js,jsx,ts,tsx}\""
   }
Enter fullscreen mode Exit fullscreen mode

🏗️ 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
Enter fullscreen mode Exit fullscreen mode
  1. Update babel.config.js:
   module.exports = {
     plugins: [
       [
         'module-resolver',
         {
           root: ['./src'],
           alias: {
             '@components': './src/components',
             '@utils': './src/utils',
           },
         },
       ],
     ],
   };
Enter fullscreen mode Exit fullscreen mode
  1. Update tsconfig.json:
   {
     "compilerOptions": {
       "baseUrl": "./src",
       "paths": {
         "@components/*": ["components/*"],
         "@utils/*": ["utils/*"]
       }
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Use clean imports:
   import Button from '@components/Button';
Enter fullscreen mode Exit fullscreen mode

🤖 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
Enter fullscreen mode Exit fullscreen mode
  1. Configure Husky in package.json:
   "scripts": {
     "prepare": "husky install"
   },
   "lint-staged": {
     "**/*.{js,jsx,ts,tsx}": [
       "eslint --fix",
       "prettier --write",
       "git add"
     ]
   }
Enter fullscreen mode Exit fullscreen mode
  1. Create a pre-commit hook:
   npx husky add .husky/pre-commit "npx lint-staged"
Enter fullscreen mode Exit fullscreen mode

🏆 Additional Best Practices

📁 A. Directory Structure

Organize files by feature or domain:

assets/
src/
  ├── components/
  ├── screens/
  ├── utils/
  ├── hooks/
  └── store/
Enter fullscreen mode Exit fullscreen mode

🧪 B. Testing

Add Jest for unit tests and Detox for E2E testing:

npm install --save-dev jest @testing-library/react-native detox
Enter fullscreen mode Exit fullscreen mode

🔥 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! 🚀

Top comments (0)