question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to improve the performance of multiple TextInput in a parent component?

See original GitHub issue

So I was designing a form that allows users to dynamically add/remove entries, where an entry contains a Select and TextInput component:

image

The naive implementation is to create a parent component that keeps the state of each entry and passing the required states and several callbacks as props to the children component, so that the parent can control the children and track the state change. However, the performance is bad with just around ten entries created. Input is slightly lagged, and you won’t see characters coming out one-by-one when holding a key. It just freezes when a key is pressed, and then a bunch of characters coming up after released the key.

Here’s the code example. Click Add icon to add more entries: https://codesandbox.io/s/dynamic-input-state-in-parent-qy9pc?file=/src/App.js

I have another design that keeps the state of TextInput and Select inside the children component. The parent component uses an instance variable instead of state to track children’s state, so that children state changes won’t trigger rendering. This design does improve the performance, but I’m just a few months into React so I’m not sure this the correct way to use React.

I’m wondering how can I improve the performance? The performance is acceptable when using pure React (with only div, input, button…).

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
haloclinecommented, Nov 13, 2020

Update: I have been able to recreate the issue and have also confirmed @IanKBovard’s suspicion that the re-renders are being caused by components consuming FormContext.

Using React Dev Tool’s Profiler, we can see that when a input value is updated, two commits result:

  1. The user’s action
  2. Side effects caused by the action

When evaluating the side effects commit, we see that a changed input value causes each of the <Select /> and <TextInput /> contained in the <Form /> to re-render. We can also see that @johnliu55tw’s memoization of the dynamic entry component is effective, preventing re-renders of that component, but not it’s Select and TextInput children.

Screen Shot 2020-11-13 at 1 12 24 PM

Additionally, the render time scales linearly with each additional input added, which is why we see visible performance degradation as 6+ of the dynamic form entries being added.

<Select /> renders are ~4X more costly than <TextInput />, so I am focussing on Select for the rest of this update.

When inspecting what is causing <Select /> to render, we see that is because its Hooks changed.

Screen Shot 2020-11-13 at 1 13 29 PM

Unfortunately, React Dev Tools does not currently have a mechanism to identify which hooks have changed. That is because hooks are currently anonymous. I have, however, been able to isolate the utilization of FormContext. When excluded from Select, we do not see Selects re-rendering; when included, all Selects re-render. So, the consumption of FormContext should be the focus for optimization.

The effect of these re-renders is amplified when <TextInput /> is interacted with because each keystroke is setting an updated value in FormContext.

I am exploring a few different patterns to address, but have not yet gotten to a working solution. I have begun exploring the options Dan lists here, including:

  • Splitting contexts
    • I have not yet attempted implementing splitting contexts yet
  • Memoization approaches (React.memo / React.useMemo)
    • I have applied a memoization approach to Select, however do not have a fully functional solution yet due to Select’s need to access the setValue function returned from FormContext.

A fourth approach to explore could be this strategy.

1reaction
haloclinecommented, Nov 5, 2020

Thank you for the follow up @johnliu55tw. I will attempt to recreate using your approach. Appreciate you providing the confirmation and detail.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to maximize performance in React when taking ...
I have created a Parent component that has multiple child components. Each of these child components have data that is passed down to...
Read more >
Text-Inputs and Performance in React (and React Native)
Any component that is independent of the text-input value can use React.memo (and kin) to avoid the being re-rendered needlessly. This is the ......
Read more >
Preventing parent component re-rendering of a big React ...
First, I have had huge forms with 100+ input fields in them that when you render too much does cause noticeable input lag...
Read more >
Optimizing performance in a React application - LogRocket Blog
We've learned that a state update in a parent component re-renders the parent and its child components. So, to ensure re-rendering a component...
Read more >
How To Avoid Performance Pitfalls in React with memo ...
You can use the useCallback Hook to preserve a function across re-renders. This will prevent unnecessary re-renders when a parent component ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found