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.
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.
To optimize React rendering, you need to make sure that components receive only necessary props. It will let you control the CPU consumption and avoid over-rendering unnecessary features. The solution is to create a functional component that will collect all props and redistribute them to other components.
2. useMemo() Hook. React allows developers to use a useMemo() hook, where we can use the optimization technique of Memoization.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With