React Native setup with Expo Router, NativeWind, and TypeScript

React Native setup with Expo Router, NativeWind, and TypeScript

ยท

5 min read

- React Native

React Native lets you develop native mobile applications using React. You will have to use different elements like View, Text, and TouchOpacity instead of div, p, and button but the underlying logic is the same and you can apply what you already know about React like different hooks (useState(), useEffect(), etc.) or different libraries like Redux Toolkit.

In this article, I will explain the steps you need to take to have a working setup so you can start developing using React Native.

- Expo

Expo to React Native is what Next.js is to React. it's a framework that provides all the necessary utilities you need for making a modern React Native application like Development Server, Routing, etc.

Expo also offers a file-based routing very similar to the one offered by Next.js.

To install Expo with file-based routing and TypeScript support, use the following command:

npx create-expo-app --template

when prompted to choose a template, select the Navigation (TypeScript) template.

- Running your application on your phone

To run the dev server you can use the following command:

npm run start

You will be presented with a QR code and addresses you can enter manually to connect to the dev server.

Next, Install the Expo app on your phone, open it, and scan the QR code to connect to the dev server, and interact with your application.

  • On Windows, you need to open the 8081 port in your firewall. (allow it in the Inbound Rules if you're using the default Windows firewall)

  • You can also use the Android Emulator in Android Studio to test your application.

- Routing in Expo

Similar to the file-based routing in Next.js (app directory), You can make new directories in the app directory to present new routes or use dynamic routes like [id] as well.

An example setup:

/app
  /books
    /index.tsx
  /book
    /[id].tsx
  /_layout.tsx
  /index.tsx

You can use the useRouter() hook to access the router and push a new path to it to navigate to another page.

import { Text, TouchableOpacity } from 'react-native';
import { useRouter } from 'expo-router';

const MyComponent = () => {
  const router = useRouter();
  return (
    <TouchableOpacity onPress={() => router.push('/books')}>
      <Text>Show all books</Text>
    </TouchableOpacity>
  );
};

export default MyComponent;

- NativeWind

You've most likely worked with or at least heard about Tailwind CSS. It allows you to use pre-defined class names to add CSS rules to your elements instead of writing new classes yourself or using the style property.

NativeWind lets you use Tailwind CSS classes in React Native and can simplify and speed up the styling process. Especially if you've worked with Tailwind CSS before.

In order to add NativeWind to your project, follow these steps:

1. install NativeWind using the following commands:

npm i nativewind
npm i -D tailwindcss

2. Edit the tailwind.config.js file and add the directories containing your tsx files to the content array:

content: ['./app/**/*.{js,jsx,ts,tsx}', './components/**/*.{js,jsx,ts,tsx}'],

3. Edit the babel.config.js file and add 'nativewind/babel' to the plugins array:

plugins: [
  ...,
  'nativewind/babel',
],

Note: If you've not installed Expo using the mentioned template and are getting the No overload matches this call. error when adding the className property to your elements, Add a .d.ts file like app.d.ts to the root of your project and add the following line to it:

/// <reference types="nativewind/types" />

You can also use this line instead:

/// <reference types="expo-router/types" />

- Path Alias (@)

When importing components from within nested components, instead of using ../../../components/Component, it's better to use a path alias that points to the root of your project like @, and shorten your import paths using it like @/components/Component.

Next.js already has this setup out of the box but for Expo, you need to add it manually.

First, open your tsconfig.json file and add the following line to it:

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

Next, open the app.json file and enable the experimental tsconfigPaths feature:

{
  "expo": {
    "experiments": { "tsconfigPaths": true }
  }
}

Now you can use the @ path alias to shorten your paths.

- Environment Variables

When storing sensitive information like API keys, you need to store them in a .env file so you can use it in production but don't push it to GitHub and leak your API key. It also allows you to manage the information easier.

In Expo like Next.js, you can achieve this using a .env.local file:

EXPO_PUBLIC_API_KEY=0123456789

You can then access the variable in your app using:

process.env.EXPO_PUBLIC_API_KEY
  • Environment variables are stored as plain text and can still be accessed by end users. if you want to hide something from end users, you would need to use an Orchestration Layer (an API or serverless function acting as a middle-man between your application and the final API) but it's out of the scope of this article.

  • If you're using an older version of Expo that does not support environment variables by default, you can use the react-native-dotenv package.

- Icons

To add icons to your React Native application, you can use the @expo/vector-icons package (installed by default). it comes with many different icons and should cover all your needs. to see a list of available icons and how to add them to your project, check this website: icons.expo.fyi


๐ŸŽ‰ You should now have a working setup and can start developing your first application!

ย