Passing Props to Child Components in React using TypeScript
Tags: react, javascript, node, beginners
Published: 2021-08-02 21:53:26

I believe that if you are reading this article, you already have an idea of component hireraquia and the normal flow is to pass props from the parent component to the child component.

I believe we all had some friction trying to convert our JavaScript knowledge to TypeScript, even though it was the same the code became more verbose and suddenly you started questioning everything.

I continue with several challenges on a daily basis, however today I am fully aware of the advantages that TypeScript brings to my application development experience in React.

Exactly today I'm going to give a brief example of how we can pass props between components using TypeScript.

# Let's code

Pretend that the main page of your application is as follows:

```js
// @src/App.tsx

import React, { useState } from "react";

import Form from "./components/Form";

const App = () => {
  const [state, setState] = useState("");
  const handleOnSubmit = (e) => {
    e.preventDefault();
    console.log({ state });
  };
  return (
    <Form
      state={state}
      setState={setState}
      handleOnSubmit={handleOnSubmit}
      placeholder="Type some letters"
    />
  );
};

export default App;
```

And the component of our form is as follows:

```js
// @src/components/Form.tsx

import React from "react";

const Form = ({
  state,
  setState,
  handleOnSubmit,
  placeholder,
}) => {
  return (
    <form onSubmit={handleOnSubmit}>
      <input
        type="text"
        value={state}
        onChange={(e) => setState(e.target.value)}
        placeholder={placeholder}
      />
      <button type="submit">Submit</button>
    </form>
  );
};

export default Form;
```

As you may have noticed both components, both are written the same way you would in JavaScript. And you may have noticed that we passed the following properties from the parent component to the child component:

- `state` is a string;
- `setState` is a function;
- `handleOnSubmit` is a function;
- `placeholder` is a string;

But before that we have to type our own function components. This way:

```js
// @src/App.tsx

const App: React.FC = () => {
  // Hidden for simplicity
}


// @src/components/Form.tsx

const Form: React.FC = () => {
  // Hidden for simplicity
}
```

So we can go to our `Form.tsx` and create a type called Props that will be used as a generic for our component.

```js
// @src/components/Form.tsx

import React from "react";

type Props = {
  state: string;
  setState: (val: string) => void;
  handleOnSubmit: () => void;
  placeholder: string;
};

const Form: React.FC<Props> = ({
  state,
  setState,
  handleOnSubmit,
  placeholder,
}) => {
  return (
    // Hidden for simplicity
  );
};

export default Form;
```

You may have noticed an inconsistency in the previous code, in `App.tsx` the **handleOnSubmit** function takes a single argument, which is an *event*. 

While in our `Props` type of `Form.tsx` we don't have any arguments. For this we will use a React data type called `FormEvent` that will have a generic, which in this case will be the `HTMLFormElement`. 

This way we will already have the ideal data type to "handle" the form event.Like this:

```js
// @src/components/Form.tsx

import React, { FormEvent } from "react";

type SubmitEvent = FormEvent<HTMLFormElement>;

type Props = {
  state: string;
  setState: (val: string) => void;
  handleOnSubmit: (e: SubmitEvent) => void;
  placeholder: string;
};

const Form: React.FC<Props> = ({
  state,
  setState,
  handleOnSubmit,
  placeholder,
}) => {
  return (
    // Hidden for simplicity
  );
};

export default Form;
```

This way, you must have also noticed that in the input element we have an attribute that is the onChange which is actually an event, so we have to type it.

In a very similar way to what we did before. First we will import a React data type called `ChangeEvent`, then we will assign a generic which in this case will be `HTMLInputElement`. This way:

```js
// @src/components/Form.tsx

import React, { ChangeEvent, FormEvent } from "react";

type SubmitEvent = FormEvent<HTMLFormElement>;
type InputEvent = ChangeEvent<HTMLInputElement>;

// Hidden for simplicity

const Form: React.FC<Props> = ({
  // Hidden for simplicity
}) => {
  return (
    <form onSubmit={handleOnSubmit}>
      <input
        type="text"
        value={state}
        onChange={(e: InputEvent) => setState(e.target.value)}
        placeholder={placeholder}
      />
      <button type="submit">Submit</button>
    </form>
  );
};

export default Form;
```

Now we can go back to our `App.tsx`. We just need to create a type in the `handleOnSubmit` function argument, which, as you might have guessed, is an event. Like this:

```js
// @src/App.tsx

import React, { useState } from "react";

import Form from "./components/Form";

type FormEvent = React.FormEvent<HTMLFormElement>;

const App: React.FC = () => {
  const [state, setState] = useState("");
  const handleOnSubmit = (e: FormEvent) => {
    e.preventDefault();
    console.log({ state });
  };
  return (
    // Hidden for simplicity
  );
};

export default App;
```

Finally we can add a generic to our `useState()`, which in this case is a string.


```js
// @src/App.tsx

import React, { useState } from "react";

// Hidden for simplicity

const App: React.FC = () => {
  const [state, setState] = useState<string>("");
  // Hidden for simplicity
};

export default App;
```

## Conclusion

As always, I hope I was clear and that I helped you. If you notice any errors in this article, please mention them in the comments. ✏️

Hope you have a great day! 🙌 🤩