2

I'm playing with the new useTransition() hook added in React 18.

I created an app highlighting the matching names. If it matches, the item gets green, otherwise red. Here how I did it:

import { useState, useTransition } from 'react';
import people from './people.json'; // 20k items

const PeopleList = ({ people, highlight, isLoading }) => {
    return (
        <>
            <div>{isLoading ? 'Loading...' : 'Ready'}</div>
            <ol>
                {people.map((name, index) => (
                    <li
                        key={index}
                        style={{
                            color: (
                                name.toLowerCase().includes(highlight)
                                ? 'lime'
                                : 'red'
                            )
                        }}
                    >
                        {name}
                    </li>
                ))}
            </ol>
        </>
    );
};

const App = () => {
    const [needle, setNeedle] = useState('');
    const [highlight, setHighlight] = useState('');
    const [isPending, startTransition] = useTransition();

    return (
        <div>
            <input
                type="text"
                value={needle}
                onChange={event => {
                    setNeedle(event.target.value);
                    startTransition(
                        () => setHighlight(event.target.value.toLowerCase())
                    );
                }}
            />
            <PeopleList
                people={people}
                highlight={highlight}
                isLoading={isPending}
            />
        </div>
    );
};

export default App;

The JSON file contains an array of 20k people. Unfortunately, the useTransition() doesn't seem to improve performance in this case. Whether I use it or not, typing in the input is very laggy, making about a 0.5s delay between each character.

My first thought was that maybe such a big DOM tree would cause a delay in the input, but it doesn't seem the case in a raw HTML page.

Why doesn't useTransition() make typing smooth in my example?

Robo Robok
  • 21,132
  • 17
  • 68
  • 126

2 Answers2

0

The reason is because your app is running in React 17 mode.

Source: https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#deprecations

react-dom: ReactDOM.render has been deprecated. Using it will warn and run your app in React 17 mode.

Raphael Rafatpanah
  • 19,082
  • 25
  • 92
  • 158
  • 1
    I checked and it seems I actually use React 18 in a proper mode. The `index.js` says `const root = ReactDOM.createRoot(document.getElementById('root'));`. I created this app via create-react-app right before checking how `useTransition()` works. – Robo Robok Jun 06 '22 at 15:30
  • Another possible issue is that your React state is too high. https://epicreact.dev/improve-the-performance-of-your-react-forms/ – Raphael Rafatpanah Jun 07 '22 at 01:14
-1

How about wrapping PeopleList component in a memo.

As far as my understanding goes. Everytime when setNeedle is being called <App/> component is rerendering and then <PeopleList/> is also rerendering even though nothing changed in <PeopleList/> component.

  • This is neither point of the question nor how `useMemo()` works. – Robo Robok Sep 21 '22 at 07:41
  • @RoboRobok have a look at my [example](https://codesandbox.io/s/happy-saha-6z35dr?file=/src/App.tsx). – hiamnshu negi Sep 21 '22 at 14:10
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 25 '22 at 20:59