Geo*_*Hug 6 reactjs react-hooks
我遇到了一个性能优化问题,我觉得可以以某种方式解决该问题,但我不确定如何解决。
假设我有一组想要编辑的对象。父组件包含所有对象,并使用显示值并允许修改对象的编辑器组件呈现列表。
一个简化的例子是这样的:
import React, { useState } from 'react'
const Input = props => {
const { value, onChange } = props
handleChange = e => {
onChange && onChange(e.target.value)
}
return (
<input value={value} onChange={handleChange} />
)
}
const ObjectEditor = props => {
const { object, onChange } = props
return (
<li>
<Input value={object.name} onChange={onChange('name')} />
</li>
)
}
const Objects = props => {
const { initialObjects } = props
const [objects, setObjects] = useState(initialObjects)
const handleObjectChange = id => key => value => {
const newObjects = objects.map(obj => {
if (obj.id === id) {
return {
...obj,
[key]: value
}
}
return obj
})
setObjects(newObjects)
}
return (
<ul>
{
objects.map(obj => (
<ObjectEditor key={obj.id} object={obj} onChange={handleObjectChange(obj.id)} />
))
}
</ul>
)
}
export default Objects
Run Code Online (Sandbox Code Playgroud)
所以我可以使用React.memo这样当我编辑一个对象的名称时,其他对象不会重新渲染。但是,由于onChange每次都在 的父组件中重新创建处理程序ObjectEditor,因此所有对象始终都会呈现。
我无法通过useCallback在我的处理程序上使用来解决它,因为我必须将它objects作为依赖项传递,每次对象的名称更改时都会重新创建它。
在我看来,所有没有更改的对象都没有必要因为处理程序更改而重新渲染。应该有办法改善这一点。
有任何想法吗 ?
我在 React Sortly 存储库中看到,它们debounce与每个对象编辑器结合使用来改变它自己的状态。这仅允许编辑的组件在有人输入时更改和重新渲染,如果在给定的延迟内没有其他更改事件出现,则仅更新一次父组件。
handleChangeName = (e) => {
this.setState({ name: e.target.value }, () => this.change());
}
change = debounce(() => {
const { index, onChange } = this.props;
const { name } = this.state;
onChange(index, { name });
}, 300);
Run Code Online (Sandbox Code Playgroud)
这是我现在能看到的最好的解决方案,但由于他们使用setState回调函数,我一直无法找到一种方法来使用钩子进行这项工作。
您必须使用以下函数形式setState:
setState((prevState) => {
// ACCESS prevState
return someNewState;
});
Run Code Online (Sandbox Code Playgroud)
您将能够在更新当前状态值 (prevState) 时访问它。
然后,您可以使用useCallback钩子而无需将状态对象添加到依赖项数组。该setState函数不需要在依赖数组中,因为它不会在渲染中改变。
因此,您将能够React.memo在孩子上使用,并且只有那些收到不同道具(浅比较)的才会重新渲染。
以下代码段中的示例
setState((prevState) => {
// ACCESS prevState
return someNewState;
});
Run Code Online (Sandbox Code Playgroud)
const InputField = React.memo((props) => {
console.log('Rendering InputField '+ props.index + '...');
return(
<div>
<input
type='text'
value={props.value}
onChange={()=>
props.handleChange(event.target.value,props.index)
}
/>
</div>
);
});
function App() {
console.log('Rendering App...');
const [inputValues,setInputValues] = React.useState(
['0','1','2']
);
const handleChange = React.useCallback((newValue,index)=>{
setInputValues((prevState)=>{
const aux = Array.from(prevState);
aux[index] = newValue;
return aux;
});
},[]);
const inputItems = inputValues.map((item,index) =>
<InputField
value={item}
index={index}
handleChange={handleChange}
/>
);
return(
<div>
{inputItems}
</div>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1325 次 |
| 最近记录: |