RangePicker时间插件导致React项目出现页面卡死问题处理

avatar
作者
筋斗云
阅读量:0

DatePicker 组件卡死问题总结

问题描述

在 React 项目中使用 DatePicker 组件时,遇到了页面卡死的问题。组件的主要功能是使用 Ant Design 的 RangePicker 组件来选择日期范围,并将日期格式从格里高利历转换为 Moment.js 格式。

当用户在页面上交互 DatePicker 组件时,浏览器出现卡死现象,导致用户无法正常操作页面。

原因分析

经过调查和调试,发现问题主要集中在以下几个方面:

  1. 不必要的重渲染

    • 组件在每次 onChange 事件触发时,会更新 state,导致整个组件重新渲染。
    • componentWillReceiveProps 接收到数据不同后,触发组件重新渲染,使用不当会导致组件不必要的更新和重渲染。
  2. 状态同步问题

    • 直接在 handleDateChange 方法中更新 tempValue,会导致状态在短时间内频繁变化,增加了浏览器的负担。
    • 导致状态更新的冲突和性能问题。
解决方案

为了解决以上问题,我们采取了以下措施:

  1. componentWillReceiveProps
    componentWillReceiveProps 添加条件判断,防止无限循环。

  2. 引入 tempSelectedValue 作为中间状态:

    • handleDateChange 方法中使用 tempSelectedValue 来暂存用户的输入,减少直接更新 tempValue 带来的频繁重渲染。
    • 只有在必要时才更新 tempValue,确保状态变化的稳定性和一致性。
改进后的代码
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { DatePicker } from 'antd'; import moment from 'moment'; import _ from 'lodash'; import './style.less';  const { RangePicker } = DatePicker;  function transformGregorianToMoment(format) {   return _.chain(format).replace('yyyy', 'YYYY').replace('dd', 'DD').value(); }  export default class DateInput extends Component {   static propTypes = {     size: PropTypes.string, // antd Input size     format: PropTypes.string.isRequired, // gregorian format     locale: PropTypes.object,     style: PropTypes.object,     value: PropTypes.array,     onChange: PropTypes.func,     disabledDate: PropTypes.func,   };    static defaultProps = {     size: 'default',     value: undefined,     locale: {},     style: {},     onChange: _.noop,   };    constructor(props) {     super(props);     this.state = {       tempValue: props.value,       tempSelectedValue: props.value,     };   }    componentWillReceiveProps(nextProps, prevState) {     if (!_.isEqual(nextProps.value, prevState.tempValue)) {       return {         tempValue: nextProps.value,         tempSelectedValue: nextProps.value,       };     }     return null;   }    handleDateChange = (mDate) => {     const { onChange } = this.props;     this.setState({ tempValue: mDate });     onChange(mDate);   };    render() {     const {       size, style, format, locale, disabledDate,     } = this.props;     const { tempValue, tempSelectedValue } = this.state;     const momentFormat = transformGregorianToMoment(format);     const [start = new Date(), end = new Date()] = tempSelectedValue || []      return (       <span         className="dateInput"         style={{           ...style,           minWidth: 208,           display: 'inline-block',           verticalAlign: 'top',         }}       >         <RangePicker           showTime           size={size}           value={[moment(start), moment(end)]}           format={momentFormat}           disabledDate={disabledDate}           onChange={this.handleDateChange}         />       </span>     );   } } 
总结

通过引入 tempSelectedValue 作为中间状态,使用 getDerivedStateFromProps 方法代替过时的生命周期方法,有效地解决了组件重渲染和状态同步问题,成功避免了浏览器的卡死现象。这个方法不仅提高了组件的性能,还增强了代码的可维护性和可读性。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!