为了提高性能,我正在尝试在我的一些组件上实现shouldComponentUpdate。我们以通常的方式进行 - 拥有不可变模型并进行参考比较。它在很大程度上起作用,但我一直想知道我是否正确处理道具中的功能。
基本上,我的问题是:在shouldComponentUpdate中,你通常用道具中的函数做什么?你是否忽略了他们altoghether,或者你试图以某种方式比较它们?
以下是一个例子:
var Inner = React.createClass({
shouldComponentUpdate(newProps){
return ???
},
render(){
return <div onClick={this.props.onClick} />;
}
});
var Outer = React.createClass({
getInitialState(){ return {value: 0}; },
render(){
var val = this.state.value;
return <div>
<span>{val}</span>
<Inner onClick={() => { this.setState({value: val + 1}) }} />
</div>
}
});
假设我需要Inner组件来拥有shouldComponentUpdate(假设它被渲染很多次并且很难渲染)。你会如何实现它?我尝试了以下方法:
1)this.props.onClick === newProps.onClick - 如果继续传递相同的方法,则有效,但在本例中不起作用,因为该方法是内联创建的。
2)this.props.onClick.toString()=== newProps.onClick.toString() - 如果函数在闭包中没有任何陈旧的情况下工作 - 在这里不起作用,因为val
在函数的闭包中。
3)正如Michael指出的那样,你可以忽略shouldComponentUpdate中的函数,但问题与2)相同。
所有这些方法都可以引入微妙的错误,是否有更简单的方法来做到这一点?我知道重写这个例子很容易,但是理想情况下我希望能够将shouldComponentUpdate行为提取到尽可能健壮的mixin中,而不是适应这些问题。
答案 0 :(得分:1)
我不相信在你的shouldComponentUpdate
中跳过功能是不可取的,但承认它有时是不可避免的。
首先,关于内联方法的第一点。在安全有效地重新渲染组件时,这将总是给您带来困难,因此我建议尽可能不使用内联方法。你的例子可以达到同样的目的:
class Inner extends React.PureComponent {
// PureComponent performs the shallow equal check
render(){
return <div onClick={this.props.onClick} />;
}
};
class Outer extends React.Component {
constructor(props) {
this.state = { value: 0 };
}
increment = () => {
this.setState({ value: this.state.value + 1 });
}
render() {
return (<div>
<span>{val}</span>
<Inner onClick={this.increment} />
</div>);
}
};
如果你已经用尽了这个选项并且它看起来不适用于你拥有的用例,那么你当然可以用自定义shouldComponentUpdate
来编写为你跳过的功能我认为这将是最好的解决方案。只要确保每次都没有令人讨厌的惊喜;如果您的函数具有在组件生命周期中发生变化的依赖关系,那么重新考虑您的方法或将这些依赖关系传递为常规props
(这将触发更新),如果它们还没有。
这里有helpful package你可以使用(虽然我还没有尝试过)。祝你好运!
答案 1 :(得分:0)
快速的想法是遍历所有键,而typeOf是一个函数,然后不检查,如果不是 - &gt;然后检查。我怀疑第一级有很多道具孩子,所以不应该慢。
也可以使用下划线比较对象http://underscorejs.org/#isEqual,但是,我还没有检查