在基于简单存储的路由器中不必要的重新渲染
Unnecessary re-render in simple store based router
我创建了一个简单的路由器,它只根据单个存储的当前状态进行路由。路由器查看它的每一个子路由,提取它的select
状态,然后测试该路由是否应该根据它的when
属性显示。
var Router = React.createClass({
render: function() {
const {children, state} = this.props;
const activeRoute = React.Children.toArray(children).find(when);
return React.createElement(
activeRoute.props.component,
Object.assign(
{},
activeRoute.props.select(state),
{
setState: this.props.setState,
}
)
);
function when(child) {
return child.props.when(child.props.select(state));
}
}
});
var Route = React.createClass({
getDefaultProps: function() {
return {
select: identity,
when: alwaysTrue,
}
},
render: function() {
throw new Error('Route should never render');
},
});
这些组件可以这样使用。
<Router state={this.state} setState={this.sState}>
<Route component={Pets} when={this.onPets} select={this.selectPets} />
<Route component={Home} />
</Router>
当使用why-did-you-update
时,我发现它是不必要的重新渲染。我想消除这些不必要的重新渲染,但我没有这样做。导致重渲染的原因是什么?如何避免重渲染?
这里有一个工作演示。点击"查看宠物(点击这里)"可以看到控制台发出一系列可避免的重新渲染警告。
事实证明,why-did-you-update
是警告我们,因为children
属性之间的两个渲染是相等的,但不是相同的引用。这是因为我们在每次渲染时返回新的React.createElement
。
为了纠正这个问题,我可以将children
移动到this.props
, this.state
, app
上的属性,甚至全局。如果我使用es6类而不是createClass
,我可以创建一个实例变量。使用这些方法之一,我可以在渲染方法中传递children
。
<Router state={this.state} setState={this.sState} children={routes} />
相关文章:
- AngularJS UI路由器不能像ng路由器那样工作
- 骨干模型默认值-todos.js示例中不必要的代码
- 当需要身份验证时,ui路由器不会重定向
- react-带有路由器的路由器不插入路由器
- RadTreeView在IE11不必要的触发事件中不起作用
- “期望赋值或函数调用,而是看到了表达式.” - 不必要的控制台.log
- 避免在 Angular.js 中对绑定值进行不必要的评估
- 避免在视差滚动效果中对图像进行不必要的缩放
- Redux防止不必要的渲染
- Requirejs+Backbone.js:类型错误:Can't在路由器中传递-路由器不是一个函数
- angular ui路由器不工作
- Javascript - 预填充 cookie 信息,以在指向外部站点的链接上交叉传递不必要的登录页面
- ExpressJS路由器不工作
- AngularJS路由:URL中不必要的参数
- 简化这个不必要的JavaScript
- 反应.js传递参数时路由器不在 URL 中
- 如何在使用 Sentry 时避免来自第三方扩展的不必要的崩溃报告
- Angular (1.5.0) ng 路由器不工作
- 角度路由器不选择子状态(嵌套状态)
- 在基于简单存储的路由器中不必要的重新渲染