Adding TypeScript to Existing React Project

Installation

First install it into the project:

npm install --save typescript @types/node @types/react @types/react-dom @types/jest

or

yarn add typescript @types/node @types/react @types/react-dom @types/jest

Next, rename any file to be a TypeScript file (e.g. src/index.js to src/index.tsx). Type errors will start to show up.

Generate tsconfig.json file

Although the React documentation says that you are not required to make a tsconfig.json file because one will be made automatically for you, that was not my experience. After doing the installation, a tsconfig.json file was not generated for me.

I had to run the following command to generate the file:

npx tsc --init

Now, you should be able to run your React project with TypeScript, if there are no TypeScript errors.

React Error: Attempted import error ‘X’ is not exported from

This error occurs when you try to import something that is not present in the specified file. When solving this error, check to make sure you are using the corresponding import and export mechanisms.

Default exports

Default exports are useful to export only a single object, function, variable. You can have only one default export per file.  

How to make a default export:

export default function Component() {
   return <h1>Hello, world</h1>
}

How to import a component with a default export:

import Component from './Component';

Notice that you do not use curly braces when importing a default export.

When importing a default export, you can use any name you want since there is only one in the file. For example:

import MyNewName from './Component';

Named import

You can have more than one named exports per file.

How to make a named export:

export function add(a, b) {
    return a + b;
}

export function subtract(a, b) {
    return a - b;
}

How to export multiple named modules at once:

export {
   add,
   subtract,
}

How to import a named export:

import { add, subtract } from './another-file';

When using named imports, the name of imported module must be the same as the name of the exported module.

You can also import both a default module and a named module on the same line, like so:

import Component, { add } from './another-file';

Testing Event Handlers in React Testing

In this short article, you will learn how to test event handlers, such as button clicks, with React Testing.

First, we will create a simple component to test:

import React from "react";

export default function ButtonWrapper({ title, ...props }) {
  return <button {...props}>{title}</button>;
}

This ButtonWrapper component takes in a title prop and any other props and returns a standard JSX button element.

Now, create a testing file with the same name as the component file and a .test.js extension (or .test.tsx if you are using TypeScript) (i.e. ButtonWrapper.test.js)

First, import the following from React testing and import the component:

import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import ButtonWrapper from "./ButtonWrapper";

Now, create the test and give it a name (i.e. "handles onClick")

test("handles onClick", () => {
 
})

Render the ButtonWrapper component:

render(<ButtonWrapper title={"Add"} />);

We will add an onClick property to the button and call the jest.fn() function whenever the component is clicked:

const onClick = jest.fn();
render(<ButtonWrapper onClick={onClick} title={"Add"} />);

jest.fn() is a function created by Jest which tracks how often it is called. In other words, it will keep track of how many times the button component is clicked.

Now, we will get access to the button and click it using fireEvent.click():

const buttonElement = screen.getByText("Add");
fireEvent.click(buttonElement);

fireEvent.click() simulates a click on the button element.

Next, we will write an assertion for how many times the button has been clicked. First, we will write an inaccurate assertion:

expect(onClick).toHaveBeenCalledTimes(0);

Now, we will run our test:

yarn test

This test will not pass because we know that the button was clicked once by the fireEvent call. The output should look like this:

Basically, React Testing is saying that it expected 0 calls to be made, but it received 1 call.

Now, let’s make a correct assertion:

expect(onClick).toHaveBeenCalledTimes(1);

The output should look like this:

Here is the final code:

import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import ButtonWrapper from "./ButtonWrapper";

test("handles onClick", () => {
  const onClick = jest.fn();
  render(<ButtonWrapper onClick={onClick} title={"Add"} />);
  const buttonElement = screen.getByText("Add");
  fireEvent.click(buttonElement);
  expect(onClick).toHaveBeenCalledTimes(1);
});

Now, you can test event handlers in React Testing. Thanks for reading!