【问题标题】:Can re-rendering of all inputs be avoided when passing a whole object?传递整个对象时是否可以避免重新渲染所有输入?
【发布时间】:2020-04-29 05:20:47
【问题描述】:

我有很多不同的接口,有很多属性,比如

interface IEntity1 {
    a: string
    b: number
    c: string
    ....
}

当我想编辑一个对象(即创建一个修改后的副本)时,我可以这样做

function Editor(props: {entity: IEntity1, setEntity(e: IEntity1) => void}) {
    const {entity, setEntity} = props;
    const [a, setA] = useState(entity.a);
    const [b, setB] = useState(entity.a);
    ....
    function handleOk() {
       setEntity({a, b, c, ...});
    }

    return <div>
       <input value={a} onChange={e => setA(e.target.value}/>
       <input value={''+b} onChange={e => setB(+e.target.value}/>
       <input value={c} onChange={e => setC(e.target.value}/>
       ...
       <button onClick={handleOk}>OK</button>
    </div>;
}

这很好用,但它非常重复。所以我创建了一个“通用”组件,它可以处理数字、字符串和其他输入。使用它,我可以处理循环中的所有字段,例如

{fieldNames.map(f => <Edit value={entity[f]}
                       onChange={newValue => setEntity({...entity}, {[f]: newValue})}/>)}

我可以轻松地生成所有需要的元数据(为简单起见,上面只是fieldNames: string[])。我可以做得更好

{fieldsMetadata.map(f => <Edit2 entity={entity} field={f}/>)}

Edit2 是一个“更智能”的组件。 困扰我的是所有我的编辑都会重新渲染任何更改。这可能是一个过早的优化,但考虑到我想在许多页面上多次使用此组件,这可能是一个有效的问题。

所以我想问是否可以编写这样一个组件而无需每次都重新渲染,或者我是否缺少与性能相关的东西?

【问题讨论】:

  • 功能组件在渲染时都会重新渲染子组件。您可以使用 PureComponents 或带有功能组件的 memo HOC 来提示根据前一个和下一个道具的 caparison 对跳过渲染做出反应。

标签: reactjs react-hooks rendering


【解决方案1】:

您的组件重新渲染的问题是因为传递了在每次渲染时再次创建的内联箭头函数

一旦你避免使用它,你可以使用 React.memo 或 PureComponent 来实现每个 Edit 组件,具体取决于你是作为功能组件还是类来实现它

const onChange= useCallback((name, value) => {
     setEntity(prev => ({...prev, [name]: value}));
}, []);
 ...
{fieldNames.map(f => <Edit name={f} value={entity[f]}
                       onChange={onChange}/>)}

编辑组件就像

const Edit = (props) => {
    const {value, name, setEntity} = props;
    const handleChange = (e) => {
         const newValue = e.target.value;
         onChange(name, newValue);
    }

    return <input value={value} name={name} onChange={handleChange} />

}

export default React.memo(Edit)

P.S 请确保您使用 setEntity 正确合并状态

【讨论】:

  • 您确定useCallback 挂钩的空部门吗?我做了类似的事情并且得到了一个损坏的组件,其中编辑一个字段导致对另一个字段的更改丢失。
  • @maaartinus 是的,空依赖是正确的。状态更新需要正确合并。看看我在帖子里是怎么做到的
猜你喜欢
  • 2023-02-07
  • 1970-01-01
  • 1970-01-01
  • 2021-04-15
  • 2020-12-26
  • 2021-10-10
  • 2021-03-12
  • 2018-12-16
  • 1970-01-01
相关资源
最近更新 更多