Skip to content

A potential bug in React 18 with Safari where it sometimes skips rendering even when the props have changed.

Notifications You must be signed in to change notification settings

evanbernstein/React18SafariSkipRenderPropsChanged

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Potential Bug in React 18 with Safari

This is either a demonstration of a bug with React 18 (18.2.0) in Safari, or a demonstration of how I don't quite understand React rendering.

It seems that React 18 in Safari is not always rendering every render call, even if the props have changed. Is this a bug?

This is a very small portion of a React/Typescript/Python game that I've been coding. This is a very trimmed down demonstration of the bug.

The game displays a text log of the players' actions. These messages get sent from the server, usually one at a time. Sometimes these messages arrive in quick succession, ms apart. I don't have the game server send all of the log messages every time, only the latest message. So the log needs to retain previous messages to have them continue to be displayed to the user.

In this bug demonstration app there are two Components:

  • LogWithState is the simplification of the Log from my game. It uses state to remember previous messages and then loops through all the messages to display them.
  • LogWithoutState takes an array of messages and loops through and displays them all. This is a workaround solution for React 18 rendering in Safari. For this to work, the app remembers the list of previous messages in Typescript not in the React component.

LogWithState uses useState to record the full list of messages in the Log component. This worked fine with React17's render call. When I upgraded to React18 and createRoot I noticed that log messages were sometimes missing. Recently I discovered that this is not reproducible in Firefox or Chrome, but is easily reproducible in Safari 16.4 and Safari Mobile iOS 16.4.1 (the latest versions as of 2023-04-21) both on my devices and on at least one other device.

The html for this demo has two root nodes for react. We use ReactDOM from React 17 to render into react17-root. We use createRoot and React 18's render to render into react18-root.

In the React 17 dom we render LogWithState to demonstrate that this works fine.

In the React 18 dom, we render two different components. LogWithState and LogWithoutState.

As you can hopefully see for yourself, "LogWithState - React 17" and "LogWithoutState - React 18" display all 10 of the log messages. "LogWithState - React 18" should be missing some of the logs. Below is an example screenshot on my machine:

screenshot of the bug in action

To see this bug in action on your own computer

  • clone this repo
  • yarn install
  • yarn start
  • Open http://localhost:3000 to view it in the bug in action in Safari mobile or desktop.

About

A potential bug in React 18 with Safari where it sometimes skips rendering even when the props have changed.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published