我有一个PureComponent可以渲染另一个组件并实现其onClick
回调:
class ColorPicker extends React.PureComponent {
render() {
console.log('ColorPicker being rendered');
const fields = this.props.colors.map((color, idx) => {
const fieldProps = {
key: `${idx}`,
color,
/*onClick: () => { // PROBLEM HERE
this.props.colorPicked(color);
}*/
};
return <ColorField { ...fieldProps}/>;
});
return (
<div className="bla-picker">
<div>{`Refresh seed: ${this.props.seed}`}</div>
{fields}
< /div>
);
}
}
此组件有一个小问题:每当重新渲染ColorPicker
时,嵌套的ColorField
也需要重新渲染,因为它们的onClick
属性会发生变化每一次。每当呈现组件时,使用lambda函数都会创建该函数的新实例。
我通常通过将onClick
的实现移到render
方法之外来解决此问题,例如:onClick: this.handleClick
。但是,我在这里不能这样做,因为onClick
处理程序需要捕获color
变量。
解决此类问题的最佳实践是什么?
这里有jsfiddle可以尝试;并作为摘要:
class ColorField extends React.PureComponent {
render() {
console.log('ColorField being rendered');
const divProps = {
className: 'bla-field',
style: {
backgroundColor: this.props.color
},
onClick: this.props.onClick
};
return <div { ...divProps}/>;
}
}
class ColorPicker extends React.PureComponent {
render() {
console.log('ColorPicker being rendered');
const fields = this.props.colors.map((color, idx) => {
const fieldProps = {
key: `${idx}`,
color,
/*onClick: () => { // PROBLEM HERE
this.props.colorPicked(color);
}*/
};
return <ColorField { ...fieldProps}/>;
});
return (
<div className="bla-picker">
<div>{`Refresh seed: ${this.props.seed}`}</div>
{fields}
< /div>
);
}
}
class Layout extends React.PureComponent {
constructor(props, ctx) {
super(props, ctx);
this.state = {
seed: 1
};
}
render() {
const pickerProps = {
colors: ['#f00', '#0f0', '#00f'],
colorPicked: (color) => {
console.log(`Color picked: ${color}`);
},
seed: this.state.seed
};
return (
<div>
<div
className="bla-button"
onClick = {this.btnClicked}
>
{'Click Me'}
</div>
<ColorPicker { ...pickerProps} />
</div>
);
}
btnClicked = () => {
this.setState({ seed: this.state.seed + 1 });
};
};
ReactDOM.render( <
Layout / > ,
document.getElementById("react")
);
.bla-button {
background-color: #aaa;
padding: 8px;
margin-bottom: 8px;
}
.bla-picker {}
.bla-field {
width: 32px;
height: 32px;
}
<div id="react">
</div>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
只要onClick
仍被注释掉,则种子更改时仅重新渲染ColorPicker
(请参见console.log
的输出)。放入onClick
后,所有ColorField
也会重新渲染。
答案 0 :(得分:2)
您可以在ColorField组件中实现shouldComponentUpdate
,例如:
class ColorField extends React.Component {
shouldComponentUpdate(nextProps) {
return this.props.color !== nextProps.color;
}
render(){
const { color, onClick } = this.props;
console.log('Color re-rendered');
return (
<div
className="color"
onClick={onClick}
style={{
backgroundColor: color,
height: '50px',
width: '50px',
}}
/>
)
}
}
请注意第一种解决方案,因为我们自己实现shouldComponentUpdate
,所以只能使用React.Component。