React表单调用heavyCalculation慢函数导致输入卡顿 不修改慢函数如何优化
问题根因
- 每次修改任意输入框时,App组件的form状态更新触发整体重渲染,所有6个Input组件都会跟着重渲染
- 每个Input组件重渲染时都会无差别执行一次
heavyCalculation慢函数,6次叠加导致输入卡顿 - 未对
handleChange做引用缓存,未对Input做渲染阻断,导致大量无必要的重渲染
解决方案
不需要修改heavyCalculation本身,按以下两步调整即可:
- 用
React.memo包裹Input组件,只有当Input的props发生变化时才触发重渲染;同时用useMemo缓存heavyCalculation的执行,无依赖的情况下只会在组件挂载时执行1次 - 用
useCallback缓存App中的handleChange函数,同时改成函数式更新form状态,避免依赖外层form变量导致引用频繁变化
修改后的App.js代码
import React, { useState, useCallback } from "react"; import Input from "components/Input"; import Button from "components/Button"; import { Card } from "antd"; import "antd/dist/antd.css"; import * as S from "./style"; const App = () => { const [form, setForm] = useState({ userName: "", email: "", password: "", firstName: "", lastName: "", city: "" }); // 用useCallback缓存引用,函数式更新不需要依赖外层form const handleChange = useCallback((fieldName, value) => { setForm(prevForm => ({ ...prevForm, [fieldName]: value })); }, []); const handleSubmit = () => { console.log(form); }; return ( <S.Content> <Card title={"Sign Up"} bordered={false} style={{ width: 500, height: 450 }}> <S.Form> <Input value={form.userName} fieldName="userName" onChange={handleChange} placeholder="Username" /> <Input value={form.email} fieldName="email" onChange={handleChange} placeholder="Email" /> <Input value={form.password} fieldName="password" type="password" onChange={handleChange} placeholder="Password" /> <Input value={form.firstName} fieldName="firstName" onChange={handleChange} placeholder="First Name" /> <Input value={form.lastName} fieldName="lastName" onChange={handleChange} placeholder="Last Name" /> <Input value={form.city} fieldName="city" onChange={handleChange} placeholder="City" /> <Button onClick={handleSubmit} label="Submit" /> </S.Form> </Card> </S.Content> ); }; export default App;
修改后的Input组件代码
import React, { useMemo } from "react"; import { heavyCalculation } from "global"; import * as Antd from "antd"; // 用React.memo包裹,仅props变化时重渲染 const Input = React.memo(({ fieldName, value, onChange, placeholder }) => { // 无依赖的useMemo,仅组件挂载时执行一次heavyCalculation useMemo(() => { heavyCalculation(); }, []); const handleChange = (e) => { onChange(fieldName, e.target.value); }; return <Antd.Input value={value} onChange={handleChange} placeholder={placeholder} />; }); export default Input;
如果实际业务中heavyCalculation需要依赖某个变量,只需要把对应的变量加到useMemo的依赖数组中,就只会在依赖变化时重新执行,不会每次重渲染都运行。
内容的提问来源于stack exchange,提问作者Mickael Zana
相关产品推荐
相关产品推荐

