Type Checking in React
Tags: react, javascript, props, programming
Published: 2022-02-09 01:52:57

## Introduction
We all know React, is a super power JavaScript framework that allows you to make beautiful **SPAs** (_**S**ingle **P**age **A**pplications_) websites.

React is Unidirectional Data, which means that the data in your React Application flow in one direction (_from **Parent Component** to **Child Component**_) via **props** concept.

One of your job as a developer or programmer is to anticipate all potential bugs and fix them in your code.
 
So, In this Article, we will talk about Two important Methods that can help us to manage and validate the props data that our child component receives it.

1. **Default Props**

2. **Porp Types**

--- 

## The Explaining
1. **Default Props**
Default Props is A property in React Component that allows you to set a default value to your props and it will appear if any props were not founded.

To understand **Default props** look at the below example:

**App** Component:
```javascript
function App() {
  const [users, setUsers] = useState();

  useEffect(() => {
    async function getUsers() {
      try {
        const result = await axios.get(
          "https://jsonplaceholder.typicode.com/users"
        );
        const { data: users } = result;
        setUsers(users);
      } catch (error) {
        console.log(error);
      }
    }
    getUsers();
  }, []);

  return (
    <div className="App">
      <h1>Our Users</h1>
      <Users users={users} />
    </div>
  );
}

export default App
```

**Users** Component:
```javascript
function Users({ users }) {
  return (
    
      users.map((user) => (
        <div
          key={user.id}
        >
          Name: <h2>{user.name}</h2>
          <p>
            Email: <span>{user.email}</span>
          </p>
        </div>
      ))
    
  );
}

export default Users;
```

Previous Code is for A simple Two React Components **App** and **Users** Component.

Our App component will fetch fake data for users from [**JSON Placeholder**](https://jsonplaceholder.typicode.com/) website by using  [**Axios**](https://axios-http.com/) Library, then it will store this data in a state and Finally, it will send this data to a Users  Component.

In the Users Component, We will receive data as props, and finally, we will map across it to show users' data.

Save the changes, run your project via the `npm start`  command.
and you will see this error:

![React Error Message](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgy8mxlkp3qee3a9fk45.png)

But what is Wrong Here ⁉️

This is because we did not add any default value to the **props** in the **Users** component so before we fetch our data from the server, the default value or users prop will be **undefined** so when the map method try to loop it, it will face a problem because undefined is not an array.

And this is a problem that **Default Props** Property Can Solve.
So to solve this problem, We will define the **Default Props** Property in our child component, in this case, **Users** then we will add our props data and its default value as a **key** and **value** like below:

```javascript
...
Users.defaultProps =  {
  users: []
}
```

> Note: Your default property should be valid according to the data that you will receive and the methods that you will use, in this case, our data is an array of objects, and we will use the map method on it so our default data type will be an **empty array**.


Save the changes, run your project, and Voila!!.


![Users Data Webpage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w1qjhe1ynzjfbdz1l1wx.png)

We can solve the previous problem by another ways like:

- assign the initial state for users state in App component as an empty array like this:

```javascript
...
const [users, setUsers] = useState([]);
...
```

- use logical operator `or` in our **Users** Component like this:

```javascript
(users || []).map(...)
```

All of these methods are true and you could use them in small projects which receive small props, but in big projects which deal with a lot of props, your will need your code to be cleaner and ease dealing with bugs in it, so you can use **Default Props** Property in the Big projects and other methods with a small projects.

2. **Prop Types**: 
prop-types is a package that allow you to check types of data that be send via a **props**.

It is important feature and that you should dealing with Big project and recieve a lot of data via **props**.

Let us return to our previous project. 
To use **prop-types** package we should install it in our project so we will install it by the following command:

```
npm i prop-types
```

then we will import it in our project in this case **Users** Component.

```javascript
import PropTypes from "prop-types"
```

and Know we are ready to use it.
to use it we will set it as as a property in our **Users** Component, then we will define the data types that we need our props follow it.

```javascript
...

Users.propTypes = { 
  users: PropTypes.array.isRequired
}
```
 

> Note: You must use the Identifiers for the **prop-types** variables as we used in this article and you must not change any letter from capital to small or vice versa.

Now if we pass the another type as a prop to **User** Component:

``` javascript
...
Users.propTypes =  {
  users: PropTypes.number.isRequired
}
```

We will get the following Error in Console:

![Console Error Message](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mq5c3xp6pm0q587uv8wl.png)

Which means that **prop-types** lib is working well.

**props-types** Package accept a lot of types that you can use it in your Projects and these is a few of them:

```javascript
 // Basic Types
  optionalArray: PropTypes.array
  optionalBigInt: PropTypes.bigint
  optionalBool: PropTypes.bool
  optionalFunc: PropTypes.func
  optionalNumber: PropTypes.number
  optionalObject: PropTypes.object
  optionalString: PropTypes.string
  optionalSymbol: PropTypes.symbol
    
  // An array of certain type
  PropTypes.arrayOf(ProtoTypes.number) 
 
  // An object taking on a particular shape
  optionalObjectWithShape: PropTypes.shape({
    optionalProperty: PropTypes.string,
    requiredProperty: PropTypes.number.isRequired
  })

  // An object that could be one of many types
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ])

  // An object with warnings on extra properties
  optionalObjectWithStrictShape: PropTypes.exact({
    optionalProperty: PropTypes.string,
    requiredProperty: PropTypes.number.isRequired
  })
```
 
So Our complete code for Project is:

**App** Component:
```javascript
import axios from "axios";
import { useEffect, useState } from "react";
import Users from "../Users";
import "./styles.css";

function App() {
  const [users, setUsers] = useState();

  useEffect(() => {
    async function getUsers() {
      try {
        const result = await axios.get(
          "https://jsonplaceholder.typicode.com/users"
        );
        const { data: users } = result;
        setUsers(users);
      } catch (error) {
        console.log(error);
      }
    }
    getUsers();
  }, []);

  return (
    <div className="App">
      <h1>Our Users</h1>
      <Users users={users} />
    </div>
  );
}

export default App
```


**Users** Component:
```javascript
import PropTypes, { array } from "prop-types";

function Users({ users }) {
  return users.map((user) => (
    <div key={user.id}>
      Name: <h2>{user.name}</h2>
      <p>
        Email: <span>{user.email}</span>
      </p>
    </div>
  ));
}

Users.defaultProps = {
  users: []
};

Users.propTypes = {
  users: PropTypes.array.isRequired
};

export default Users;
```

---

## **Conclusion**
Checking Props types and set the default values to it is an important thing Especially in Big Projects, So it is better to use them in your projects.
Finally Keep Learning.