React Native setup with Expo Router, NativeWind, and TypeScript
Tags: typescript, tutorial, reactnative, tailwindcss
Published: 2023-10-20 03:18:45

### Table of Contents

- [React Native](#react-native)
- [Expo](#-expo)
- [Running your application on your phone](#running-your-application-on-your-phone)
- [Routing in Expo](#routing-in-expo)
- [NativeWind](#nativewind)
- [Path Alias (@)](#path-alias)
- [Environment Variables](#environment-variables)
- [Icons](#icons)

<a name="react-native"></a>
## - React Native
[React Native](https://reactnative.dev/) lets you develop native mobile applications using [React](https://react.dev/). 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](https://redux-toolkit.js.org/).

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.

<a name="expo"></a>
## - Expo
[Expo](https://expo.dev/) to React Native is what [Next.js](https://nextjs.org) 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.

<a name="running-your-application-on-your-phone"></a>
## - 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](https://play.google.com/store/apps/details?id=host.exp.exponent&hl=en&gl=US) 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](https://developer.android.com/studio/run/emulator) in [Android Studio](https://developer.android.com/studio) to test your application.

<a name="routing-in-expo"></a>
## - 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.

```typescript
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;
```

<a name="nativewind"></a>
## - NativeWind
You've most likely worked with or at least heard about [Tailwind CSS](https://tailwindcss.com/). 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](https://www.nativewind.dev/) 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" />
```

<a name="path-alias"></a>
## - 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.

<a name="environment-variables"></a>
## - 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`](https://www.npmjs.com/package/react-native-dotenv) package.

<a name="icons"></a>
## - 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](https://icons.expo.fyi/)

---
🎉 You should now have a working setup and can start developing your first application!