在事件处理程序中使用ReactDOM.render来避免渲染昂贵的组件
Using ReactDOM.render inside an event handler to avoid rendering expensive components
我有一个React应用程序,它有一个任务列表,每个任务都有截止日期。我希望用户能够点击截止日期,弹出一个日期选择器来选择一个新的日期。
我正在使用材质UI库http://www.material-ui.com/#/components/date-拾取器
我可以简单地为列表中的每个任务呈现一个日期选择器,但在长列表中为每个项目呈现如此复杂的组件似乎可能会导致性能问题。我更喜欢只显示截止日期,并且只在用户单击更改截止日期时呈现日期选择器。
以下是我提出的解决方案:
TaskFooter = React.createClass({
propTypes: {
task: React.PropTypes.object.isRequired
},
onDateChanged(e, newDate){
// handle data update
},
showDatePicker(){
let dp = ReactDOM.render(
<MUI.DatePicker autoOk={true} textFieldStyle={{display: 'none'}} onChange={this.onDateChanged} />,
this.refs.datePickerContainer
);
dp.openDialog();
},
render() {
return (
<div onClick={this.showDatePicker}>
<MUI.Libs.SvgIcons.ActionEvent />
{this.props.task.duedate}
<div ref="datePickerContainer"></div>
</div>
);
}
});
这似乎有效,但我想知道这种模式是否是"正确"的方法。有没有更好的方法来动态呈现可能昂贵的反应组件以响应事件?
编辑:我找到了另一种方法来做到这一点,它似乎更"反应",但我不确定它是否完全正确。
TaskFooter = React.createClass({
propTypes: {
task: React.PropTypes.object.isRequired
},
getInitialState(){
return {
showDatePicker: false
}
},
componentDidUpdate(prevProps, prevState){
if(this.state.showDatePicker && !prevState.showDatePicker){
this.refs.datePicker.openDialog();
}
},
onDateChanged(e, newDate){
console.log('new date', newDate);
this.setState({
showDatePicker: false
});
},
showDatePicker(){
this.setState({
showDatePicker: true
});
},
render() {
return (
<div onClick={this.showDatePicker}>
<MUI.Libs.SvgIcons.ActionEvent />
{this.props.task.duedate}
{ this.state.showDatePicker ?
<MUI.DatePicker autoOk={true} textFieldStyle={{display: 'none'}} onChange={this.onDateChanged} ref="datePicker" />
: ''}
</div>
);
}
});
这正确地显示和隐藏了日期选择器,但当设置关闭状态时,我在控制台中收到以下警告:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the DatePickerDialog component.
尽管有此警告,但我的组件上的状态似乎设置正确。我应该忽略这个警告吗?我的新模式正确吗?
安装React应用程序时仅使用ReactDOM.render()
。它不应该在React组件本身中使用。
熟悉状态的工作原理。我建议如下:
TaskFooter = React.createClass({
propTypes: {
task: React.PropTypes.object.isRequired
},
getInitialState() {
return {
displayDatePicker: false
};
}
onDateChanged(e, newDate) {
// handle data update
},
showDatePicker() {
this.setState({
displayDatePicker: false
});
}
componentDidUpdate(prevProps, prevState) {
// this is a little bit hacky,
// ideally there would be a prop for DatePicker to instruct it to already be open
if (this.state.displayDatePicker && !prevState.displayDatePicker) {
this.refs.dp.openDialog();
}
},
render() {
return (
<div onClick={this.showDatePicker}>
<MUI.Libs.SvgIcons.ActionEvent />
{this.props.task.duedate}
{this.state.displayDatePicker ? (
<MUI.DatePicker
ref="dp"
autoOk={true}
textFieldStyle={{display: 'none'}}
onChange={this.onDateChanged}
/>
) : null}
</div>
);
}
});
这以更清洁的方式实现了同样的目的。状态变量displayDatePicker
确定日期选择器是否显示。我还使用了componentDidUpdate()
来检测日期选择器何时刚刚被激活。
然而,还有一件事。我认为您应该质疑您的假设,即默认情况下显示日期选择器必然会产生性能问题。你知道是这样吗?我担心您可能会用代码复杂性的增加来换取微不足道的性能提升。
相关文章:
- 如何创建带有插槽的vue js组件预加载程序
- 如何向onClick事件处理程序传递一个接受参数的函数,并且仍然将该函数绑定到组件's”;这个“;上下文
- React/flux - 子组件用户事件 - 是否应通过调度程序路由所有内容
- 呈现react引导程序组件时出错
- 如何使用onClick处理程序在React组件中创建链接
- 如何在使用ui路由器时构造angular.js应用程序组件
- 将事件处理程序推送到父组件
- 多个组件点击处理程序的反应性能[每个组件的点击处理程序与点击处理程序]
- 动态生成的react引导程序组件缺少密钥属性
- React组件onClick处理程序不工作
- Gwd自定义组件及其事件处理程序
- AngularJS组件和cms驱动应用程序的最佳实践
- React.js-通过事件处理程序更改所有者组件的状态
- 使用角带和ui引导程序中的组件
- 在应用程序中识别框架组件的覆盖的工具
- Web应用程序的组件 - Express.js,Angular.js和MVC混淆
- 角度 2 交叉应用程序(根组件)通信
- 为什么当同级节点的“display”属性发生更改时,React 组件的 onClick 事件处理程序不会触发
- 是否可以避免在路由更改时重新呈现父路由处理程序组件
- 将 Bootstrap JS 组件与浏览器化填充程序一起使用