如果我在一个表单中有很多文本输入(挂钩),我该如何提高反应性能?
How can I improve the react performance if I have many text inputs (Hooks) in a form?
问题
我有一个表单可以通过 React 中的 api rest 发送数据,当我有大约 80 个文本字段时,渲染和在表单上书写的速度非常慢。
我正在使用带钩子的功能组件来处理输入文本,并使用 Material-UI 作为 UI 框架。
在第一次尝试中,我有一个柯里化函数来处理这些值:
setValue = (setter) => (e) => { setter(e.target.value) }
但是渲染过程真的很慢(因为我在每次渲染中都创建了一个函数),所以我将 setter 函数作为 prop 发送,然后它改进了一点但还不够。
实际上我在任何输入中写一个键时的输入响应大约是500毫秒。
我怎样做才能获得更好的性能?
为了便于理解,对代码进行了简化。
示例代码如下:
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" />
我的输入组件:
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>
)
}
所有输入值都必须在一个组件中,因为我需要将它们发送到带有 axios 的服务器。
看起来 Material-UI 输入组件有点重。
我有一个 sample codesandbox here,我在其中初始化了大约 1000 个输入。最初它滞后并崩溃。
首先,我向 Input
组件添加了一个 memo
。这会记住所有 Input
组件,只有当其中一个道具发生变化时才会触发新的渲染。
首先,只需将 memo
添加到您的输入组件。
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>
)
})
注意: 如果您有一个自定义的 setter,就像您的第一个案例 setValue = (setter) => (e) => { setter(e.target.value) }
,您可以将其包装在 useCallback
中以防止为每个渲染器创建多个函数。
问题
我有一个表单可以通过 React 中的 api rest 发送数据,当我有大约 80 个文本字段时,渲染和在表单上书写的速度非常慢。
我正在使用带钩子的功能组件来处理输入文本,并使用 Material-UI 作为 UI 框架。 在第一次尝试中,我有一个柯里化函数来处理这些值:
setValue = (setter) => (e) => { setter(e.target.value) }
但是渲染过程真的很慢(因为我在每次渲染中都创建了一个函数),所以我将 setter 函数作为 prop 发送,然后它改进了一点但还不够。
实际上我在任何输入中写一个键时的输入响应大约是500毫秒。
我怎样做才能获得更好的性能?
为了便于理解,对代码进行了简化。
示例代码如下:
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" />
我的输入组件:
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>
)
}
所有输入值都必须在一个组件中,因为我需要将它们发送到带有 axios 的服务器。
看起来 Material-UI 输入组件有点重。
我有一个 sample codesandbox here,我在其中初始化了大约 1000 个输入。最初它滞后并崩溃。
首先,我向 Input
组件添加了一个 memo
。这会记住所有 Input
组件,只有当其中一个道具发生变化时才会触发新的渲染。
首先,只需将 memo
添加到您的输入组件。
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>
)
})
注意: 如果您有一个自定义的 setter,就像您的第一个案例 setValue = (setter) => (e) => { setter(e.target.value) }
,您可以将其包装在 useCallback
中以防止为每个渲染器创建多个函数。