Unlocking the Power of React 18 with TypeScript

Creating a React App with TypeScript

Let’s start by creating a brand-new React app using Create React App, with TypeScript as our trusty sidekick. We’ll then upgrade the React version to @next, which will leave us with package.json entries that utilize React 18.

{
  "dependencies": {
    "react": "^18.0.0-alpha.0",
    "react-dom": "^18.0.0-alpha.0",
    "react-scripts": "^5.0.0-next.0"
  }
}

Unleashing the New APIs

Now that we’ve got our React 18 app up and running, it’s time to tap into its new features. We’ll focus on the ReactDOM.createRoot API, which is the key to unlocking React 18’s full potential.

import { createRoot } from 'eact-dom';

const root = document.getElementById('root');
const rootElement = createRoot(root);

rootElement.render(<App />);

However, when we try to use this API, TypeScript throws an error, complaining that it doesn’t recognize ReactDOM.createRoot.

The TypeScript Conundrum

The issue lies in our type definitions, which don’t yet include the new API. To resolve this, we need to upgrade our type definitions.

{
  "compilerOptions": {
    //... other options...
    "lib": ["DOM", "ESNext"],
    "types": ["node", "react", "react-dom"]
  }
}

But even after doing so, TypeScript still refuses to cooperate, throwing the same error.

A Glimmer of Hope

Fortunately, the PR that added support for the new APIs provides some valuable insights. By adding a new entry to our tsconfig.json file, we can finally get TypeScript to recognize the ReactDOM.createRoot API.

{
  "compilerOptions": {
    //... other options...
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "lib": ["DOM", "ESNext"],
    "types": ["node", "react", "react-dom"],
    "reactScriptsVersion": "5.0.0-next.0"
  }
}

The Final Hurdle

With our type definitions in place, we’re now faced with a different error: TypeScript is complaining about the possibility of document.getElementById(‘root’) returning null.

const root = document.getElementById('root');
if (root!== null) {
  const rootElement = createRoot(root);
  rootElement.render(<App />);
}

To overcome this, we simply need to ensure that root is not null before invoking ReactDOM.createRoot.

Victory at Last!

And with that, we’ve successfully created a React 18 application using TypeScript! It’s time to revel in the excitement of this new development.

Leave a Reply