Setup Vanilla React Native with TypeScript
Tags: javascript, react, reactnative
Published: 2022-04-11 14:50:08

An attempt to create a simple react native typescript project without the bells and whistles you get when using a template or boilerplate, seen to be a challenge and hardly is there any tutorial that covers these steps vividly.<br/>

So, while at it I enjoyed creating this blogpost and solving the problem highlighted above, hopefully you will enjoy it too!

#### A Little Backstory about React Native and TypeScript

React Native is an exciting framework that enables web developers to create robust mobile applications using their existing JavaScript knowledge. It offers faster mobile development, and more efficient code sharing across iOS, Android, and the Web, without sacrificing the end user’s experience or application quality. 

It’s based on React, Facebook’s JavaScript library for building user interfaces, but instead of targeting the browser, it targets mobile platforms. 
Web developers can now write mobile applications that look and feel truly “native,” all from the comfort of a JavaScript library that we already know and love. Plus, because most of the code you write can be shared between platforms, React Native makes it easy to simultaneously develop for both Android and iOS.

TypeScript is a superset of the JavaScript language that has a single open-source compiler and is developed mainly by a single vendor: Microsoft. The goal of TypeScript is to help catch mistakes early through a type system and to make JavaScript development more efficient.

#### Requirements

- Basic knowledge of JavaScript
- Basic knowledge of React
- Basic knowledge of running CLI commands
- Node.js and npm installed on your machine
- XCode or Android Studio installed on your machine
- Some experience with React Native (suggested, not required)


#### Getting Started

The first step is to install and initialise a project and it's dependencies. To achieve that we run this command in the terminal:

```
npx react-native init Foobaz 
  
```
The above commands creates a project with the name **Foobaz** with the basic setup to run our JavaScript files.

Now that we have setup the project, here is what we get out of the box:

![Screenshot 2022-04-01 at 12.52.18.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648813978294/fVPoFgqYt.png)

The project created here gives us a barebone structure for pure JavaScript files or source code.
So we have to integrate TypeScript.

#### Integrate TypeScript
The next thing is to add typescript to our app. We add these packages `@types/react` `@types/react-native`  `react-native-typescript-transformer` and integrate into our app:

```
yarn add typescript -D @types/react @types/react-native  react-native-typescript-transformer
``` 

`.ts` is the default file extension while `.tsx` is a special extension used for files which contain `JSX`

Now that we've installed these packages, in our project root, we rename this file `App.js` to `App.tsx`, so we are able to write TypeScript code and let the compiler transform our source code.

The compiler is of no help to us until we tell it what to do. In TypeScript, these rules are defined in a special file called `tsconfig.json`. 

Let's add a `tsconfig.json` file in the root of our project and paste in the following content:

```
{
  "compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "jsx": "react-native",
    "lib": ["es2017"],
    "moduleResolution": "node",
    "noEmit": true,
    "strict": true,
    "target": "esnext"
  },
  "exclude": [
    "node_modules",
    "babel.config.js",
    "metro.config.js",
    "jest.config.js"
  ]
}
```


#### Compiling TypeScript Source Code

In our `App.tsx` file, you can replace the source code in there with the one below, where we are using the fetch api to pull users list and displaying in our app.

```
import React from 'react';
import {useState, useEffect} from 'react';
import {
  FlatList,
  ActivityIndicator,
  View,
  Text,
  StyleSheet,
  SafeAreaView,
  Pressable,
  Image,
} from 'react-native';


type DataItem = {
  id: string;
  first_name: string;
  last_name: string;
  email: string;
  avatar: string;
};


const App = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [dataSource, setDataSource] = useState<DataItem[]>([]); //set the type of what the hook expects to be an array of DataItem.

  useEffect(() => {
    fetch('https://reqres.in/api/users?page=2')
      .then(response => response.json())
      .then((responseJson: {data: any}) => {
        setIsLoading(false);
        setDataSource(responseJson?.data);
       
      })
      .catch(error => {
        setIsLoading(false);
        // do something with the error...
      });
  }, []);

  if (isLoading) {
    return (
      <View
        style={{flex: 1, padding: 20, marginTop: 40, backgroundColor: 'white'}}>
        <ActivityIndicator />
      </View>
    );
  }
  return (
    <SafeAreaView
      style={styles.safeArea}>
      <FlatList
        data={dataSource}
        renderItem={({item}) => (
          <Pressable
          onPress={() => null}
          style={styles.cardContainer}>
          <View
            style={styles.cardContent}>
            <Image
              source={{uri: item?.avatar}}
              style={styles.avatar}
            />
            <View>
              <Text style={{color: '#000'}}>{item?.first_name} {item?.last_name}</Text>
            </View>
          </View>
        </Pressable>
        )}
        keyExtractor={({id}, index) => id}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  safeArea: {
    backgroundColor: 'white',
    flex: 1,
    marginTop: 80,
    marginHorizontal: 16,
  },
  avatar: {
    height: 60,
    width: 55,
    marginLeft: 16,
    marginRight: 15,
    borderRadius: 35,
    justifyContent: 'center',
    alignItems: 'center',
  },
  cardContainer: {
    marginBottom: 10,
    flexDirection: 'row',
    paddingVertical: 16,
    backgroundColor: '#EEEFF2',
    alignItems: 'center',
    justifyContent: 'space-between',
    borderRadius: 8,
    shadowColor: '#EEEFF2',
    shadowRadius: 50,
    shadowOffset: {
      width: 0,
      height: 10,
    },
    shadowOpacity: 0.1,
    elevation: 5,
  },
  cardContent: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  }
});

export default App;

```

In our `App.tsx` on  line `15` we construct a data type to define the users list expected from our api endpoint. 

On line `25` we declare a useState hook for conditional rendering to check if the data has loaded.

Also, on line `26` we declare a useState hook to hold our data to be rendered in our UI. We specified that the hook should accept an array of `DataItem`.

On line `53` we use the FlatList component, in-built into the react native package to display our UI.
[FlatList](https://reactnative.dev/docs/flatlist) is used to render list of data with minimal effort. 

#### Running Our App
Let's navigate to the root folder in our project from a code editor and run the commands below to build the UI and start the application:

```
# MacOS
yarn run ios

```

```
# Windows/Linux
yarn run android

```

This is what our app should look like:
![whitereactmobappvanilla.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1649685562315/w5VmnMcE_.png)

You can view the source code on GitHub [here](https://github.com/paulayo93/Foobaz)

#### Conclusion

Hurray!!! We are done at the moment.


Hope you enjoyed the tutorial and you were able to follow through without any errors?

Would appreciate your comments and suggestions about the tutorial in comment box. 

Also, you can reach me on twitter [@ayopaulofficial](https://twitter.com/ayopaulofficial) and on LinkedIn at [Paul Oloyede](https://www.linkedin.com/in/paulayo/)

Thanks for Reading.