How can I improve the react performance if I have many text inputs (Hooks) in a form?
It looks like the Material-UI Input component is a bit heavy.
I have a sample codesandbox here where I initialised around 1000 inputs. Initially it lagged and crashed.
To begin with I added a memo
to the Input
component. This memoizes all the Input
components, triggering a new render only if one of its props has changed.
For a start just add a memo
to your input component.
import React, { memo } from 'react';
const Input = memo(({
value, setter, text, type = 'text'
}) => {
const handleChange = (e) => {
const { value: inputValue } = e.target
setter(inputValue)
}
return (
<Grid>
<TextField
fullWidth
type={type}
label={text}
value={value}
onChange={handleChange}
multiline={multiline}
/>
</Grid>
)
})
Note: If you have a custom setter like in your first case setValue = (setter) => (e) => { setter(e.target.value) }
, you can wrap that in a useCallback
to prevent multiple functions to be created for every render.
Admin
Updated on June 04, 2022Comments
-
Admin almost 2 years
The Problem
I have a form to send data through a api rest in React, the render and the writing on the form is very slow when I have about 80 text fields.
I'm using functional components with hooks to handle the input texts and Material-UI as UI framework. In a first try, I had a currying function to handle the values:
setValue = (setter) => (e) => { setter(e.target.value) }
But the render process was really slow (because I was creating a function in every render), So I send the setter function as a prop, then it improves a little but not enough.
Actually the input response when I write a key in any input, it's about 500 ms.
What can I do to get a better performance?
The code was simplified for understanding purposes.
Sample code below:
const [input1, setInput1] = useState('') const [input2, setInput2] = useState('') const [input3, setInput3] = useState('') . . . const [input80, setInput80] = useState('') // render the Inputs <Input value={input1} setter={setInput1} text="Some label text" /> <Input value={input2} setter={setInput2} text="Some label text" /> <Input value={input3} setter={setInput3} text="Some label text" /> . . . <Input value={input80} setter={setInput80} text="Some label text" />
My Input components:
const Input = ({ value, setter, text, type = 'text' }) => { const handleChange = (e) => { const { value: inputValue } = e.target setter(inputValue) } return ( <Grid> <TextField fullWidth type={type} label={text} value={value} onChange={handleChange} multiline={multiline} /> </Grid> ) }
All input values are must be in a component because I'm need to send them to a server with axios.