TypeScript in React :Props

·

4 min read

Table of contents

We are assuming that you are familiar with using TypeScript and need help in using TypeScript in React.

Start by creating a new React project with TypeScript support built into using the following command

npx create-react-app <appname> --template typescript

Whenever we want to use TypeScript supported project we need to use the above code snippet. It usually takes a minute or more to create the app.

The folder structure will look like this:

image.png

We are now using TypeScript so if a file will contain a React component or any type of JSX code we will use the extension .tsx

If there is no JSX involved ie. the file is for Redux or Reducer will only use .ts

In src file directory, select all the files and delete them. Start fresh by creating index.tsx file. Write the following code and enter npm run start in terminal

import ReactDOM from 'react-dom';
import React from 'react';

const App = () => {
    return (<div>
        <h1>Hello World</h1>
    </div>);
};

ReactDOM.render(<App/>, document.querySelector('#root'));

The above code will compile successfully but it will show a warning as you will be asked to update to React 18. Update the code to the following snippet and console will not show any warning. Note that you can choose to ignore the warning with previous code snippet.

import ReactDOM from 'react-dom/client';
import React from 'react';


function App() {
    return (<div>
        <h1>Hello World</h1>
    </div>);
  }

  const el = document.getElementById('root');
  const root = ReactDOM.createRoot(el!);

  root.render(<App/>)

Working with props

In src folder, create a new folder of the name props. Inside props create a file name Child.tsx and Parent.tsx. The directory should look like this

image.png

For now, import the Child in Parent component and put a div inside the Child component. We will export different kinds of Child component hence avoid writing export 'default'. Look at the code snippet below:

function Child(){
    return <div>Child</div>
}

export {Child}
import {Child} from './Child';

export default function Parent(){
    return (<div>
        <Child/>
        </div>)
}

Import the Parent inside the index.tsx file else it won't render on the browser screen.

import Parent from './props/Parent';

function App() {
    return (<div>
        <Parent/>
    </div>);
  }

We will give some props to the Child so to get familiar with how props will behave with TypeScript in React.

One major change with including the TypeScript is that an interface needs to be defined inside the Child component, this will ensure two big checks by TypeScript:

  1. Whether correct props are being provided to the Child or not by Parent.
  2. Whether correct props is being typed and named before passing on to the child

Check the code snippets for further clarity.

We created ChildProps named interface in the Child component. We pass a props in the Child function declaration and declare it's type as ChildProps.

interface ChildProps{
    color: string;
}

function Child(props: ChildProps){
    return <div>Child {props.color}</div>
}

export {Child}

See how the type of props is now being checked by TypeScript. We need to make changes in the Parent component as well. We will pass a color equal to "red" while rendering the Child component from Parent. It will look like this but you can declare any color name.


export default function Parent(){
    return (<div>
        <Child color = "red"/>
        </div>)
}

If you will put any other props except color TypeScript will show an error.

Another way to tell the TypeScript how to identify our component as a React component is using React.FC. Below is the way to use it and it will work totally fine.

const Child : React.FC<ChildProps>= (props)=>{
    return <div>Child as FC {props.color}</div>
}

Now after using React.FC we will be able to use additional React JSX properties such as displayName without any error. With previous style of writing our component we cannot use the additonal properties that we get with the React JSX. React.FC is same as React.FunctionalComponent. You are free to use either of those and both will behave similarly.

Now let us add a button in our child component which has a callback function. Let us name it as onClick. Our Child component should look like this

<div>
        Child {props.color}
        <button onClick = {props.onClick}>Click here</button>
        </div>

This will start to show an error as now we have to update our interface as well.

interface ChildProps{
    color: string;
    onClick: () => void
}

Till now we have seen that we are not using any children inside the Child component. Even if you try writing something like below it will throw an error in the Parent component.

<Child props ={color, onClick}> <div>Another Component</div> </Child

This happens because we have to define a children property inside the interface. With React 18 we can do it in the following manner:

interface ChildProps{
    color: string;
    onClick: () => void;
    children?: React.ReactNode;
}

The ? symbol after children makes the children property optional. Removing the ? symbol will mean we have to put children between Child component everytime.

That's all for now for using props in React with TypeScript. In next blog I will mention ways to manage states in React using TypeScript