Typescript React Tutorial - Typescript React Props, Usestate Typescript and React Context Typescript

In this post you will learn how to use Typescript together with React.

Project generation

Our first step would be to generate a React project with Typescript. You could use for it create-react-app but I highly recommend you to look on Vite tool. It allows you to generate project with different frameworks and it is extremely fast.

To generate a project I'm using

npm create vite@latest react-ts

Where react-ts is a name of the project

Vite

Here we need to select React as a framework and choose that we want Typescript with it.

Now we can remove everything from App component and start working.

const App = () => {
  return <h1>Monsterlessons Academy</h1>
}

JSX.Element

Most often in React we create components and provide props inside. Let's say that we want to create a custom Button component.

const Button = ({
  text = "submit",
  icon,
}) => {
  return (
    <button>
      {icon && <span>{icon}</span>}
      {text}
    </button>
  );
};

const App = () => {
  return (
    <div>
      <h1>Monsterlessons Academy</h1>
      <Button text="Fooo" icon=""></Button>
    </div>
  )
}

Out Button has text and icon as props.

Now let's add a bit of Typescript. First of all let's defined what our Button must return


```javascript
const Button = ({
  ...
}): JSX.Element => {

We specified here JSX.Element which is React markup. If we return a string or undefined we will directly see a warning from Typescript.

Interface for props

Secondly let's define the interface for all possible props in our Button component. In this case it will be more safe.

interface ButtonProps {
  text?: string;
  icon?: string;
}

const Button = ({
  text = "submit",
  icon,
}: ButtonProps): JSX.Element => {

We created an interface where both properties are strings and they are optional. Not we used ButtonProps inside our props and we are sure that we won't pass any wrong props inside.

Children

Really often we have children that we want to provide to our components. How we can define them with Typescript?

interface ButtonProps {
  text?: string;
  icon?: string;
  children?: JSX.Element;
}
const Button = ({
  text = "submit",
  icon,
  children,
}: ButtonProps): JSX.Element => {
  return (
    <button>
      {icon && <span>{icon}</span>}
      {text}
      {children && children}
    </button>
  );
};

Here we added an optional children property which is essentially a JSX.Element. We also rendered children from the props inside the component if they are provided. In this case we are safe that only correct React markup can be provided as a content inside the component.

Working with React hooks

But what about React hooks? Most often you would want to provide correct data type in your useState hook.

interface User {
  id: string;
  name: string;
}
const App = () => {
  const [user, setUser] = useState<User | null>(null);
}

It makes sure that we can set and get from the user only properties which are specified. In this case it is either a User interface or null.

Working with React classes

You must also know how to work with React classes inside Typescript. Yes I know that classes is an older approach but it is still not deprecated and you might get a project with classes inside React.

interface AppState {
  currentUser?: User;
}

class App extends Component<{}, AppState> {
  componentDidMount() {
    this.setState({ currentUser: { id: "1", name: "foo" } });
  }

  render(): JSX.Element {
    return (
      <div>
        <h1>Monsterlessonss Academy</h1>
        <Button text="Fooo" icon=""></Button>
      </div>
    );
  }
}

Here we converted our App in the class. When we extend from React class we provide inside props interface as a first argument and state interface as a second argument. In our case props are empty but we created AppState interface with currentUser which we can set.

Working with React context

The last thing that I want to show you is how to work with React context.

const AppContext = createContext({ theme: "light" });
const App = () => {
  const appContext = useContext(AppContext);
  return (
    <AppContext.Provider value={{ theme: "dark" }}>
      <h1>Monsterlessonss Academy</h1>
      <Button text="Fooo" icon=""></Button>
    </AppContext.Provider>
  );
};

We didn't write any additional interfaces but just used createContext and useContext. Nevertheless Typescript fully understands what properties are available inside our context and gives us a correct autocomplete and validation in appContext when we use it.

Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!

📚 Source code of what we've done
Did you like my post? Share it with friends!
Don't miss a thing!
Follow me on Youtube, Twitter or Instagram.
Oleksandr Kocherhin
Oleksandr Kocherhin is a full-stack developer with a passion for learning and sharing knowledge on Monsterlessons Academy and on his YouTube channel. With around 15 years of programming experience and nearly 9 years of teaching, he has a deep understanding of both disciplines. He believes in learning by doing, a philosophy that is reflected in every course he teaches. He loves exploring new web and mobile technologies, and his courses are designed to give students an edge in the fast-moving tech industry.