Upgrading a create-react-app game to React 18

Join me in this (short) post as I upgrade my Word-Search React game to the new and shiny version of React 18.

The message was loud and clear in the latest React conf:

So I was like “Nice, seems like a good time to upgrade my Word-Search game to start using it.”, but other interesting things drew my attention, and so here we are now - upgrading to React 18. Let’s go!

My Word-Search game is a project which started (and continued on) as a Create-React-App project and is currently using React 16.9.0 (😱). My mission is to upgrade it to React 18 and with hopes that all remains working. I’m not going to use any of the new features React 18 offers in the course of this upgrade, but just make sure it all stays intact.

As always, I start with the docs, and surely enough they've taken me into another document which explains upgrading to React 18 on the client.
So first things first, the initial step is to actually install the new React version, but what is the new version? The docs say to upgrade to 18, but is it 18.0.0? 18.0.2? Surely not alpha or beta, right?
You know what, let’s try installing the latest version of React:

npm install react@latest react-dom@latest

Well, nope. The latest version is 17.0.2, so what do we do?

I’m heading down to the React Conf recap to find how we should install React 18. Oh, I see it now - I need to install the React RC (Release Candidate) version, which kinda throws me off tracks since in this discussion on the React-18 working group, published on May 2021, it suggests that the final release will be available at around July 2021 (Notice the dates on the image below)

No worries - let’s install the release candidate -

npm install react@rc react-dom@rc

Yeah, so my package.json now have the new rc versions of react and react-dom:

"react": "^18.0.0-rc.0",
"react-dom": "^18.0.0-rc.0",

Let’s try and fire-up the application and see the sparks -
Funny thing I noticed when running “npm start” on my upgraded create-react-app project. It modifies the root tsconfig.json file “jsx” property and now instead of being:

"jsx": "react"

It is:

"jsx": "react-jsx"

Reading the TS docs I gather that this change was introduced in React 17, and has to do with how TSC transpile JSX in React 17 and above. Good to know.

The game is up! Let’s try and play with it. I’m grabbing a word from the scattered letters, the animation and everything works well. I drop it on the matching word in the words panel to check my answer and... BOOM.
It seems that I have an issue with updating the style of the floating letters -

😳
Well, I cheated a little, since I did not completed the migration as requested, specifically this part:

// before
const container = document.getElementById('root');
ReactDOM.render(<App />, container);

// after
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(<App/>);

Let’s do that and see if it fixes the error I’m getting.
My rendering code used to be like this:

const rootElement = document.getElementById('root');
const render = () => {
   ReactDOM.render(
       <Provider store={gameStore}>
           <App />
       </Provider>,
       rootElement || document.createElement('div')
   );
};

And I modified it to be compatible with React 18, like this:

const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
const render = () => {
   root.render(
       <Provider store={gameStore}>
           <App />
       </Provider>
   );
};

Let’s check if the error I had is gone… It is! Awesome. The game works as expected :)

And so my Word-Search game is now updated with the RC version of React 18 and all seems to work well. Since the game does not have a BE involved, most of the new features of React 18 are irrelevant, but who knows… they might be relevant in the future ;)
As always, if you have any ideas on how to make this better or any other technique, be sure to share with the rest of us!

Hey! If you liked what you've just read check out @mattibarzeev on Twitter 🍻

20