2017-09-16 90 views
0

我一直在试图派遣在componentDidMount动作,遗憾的是我得到:作出反应componentDidMount()调度动作

最大调用堆栈大小超过

import React, { Component } from 'react'; 
import ReactDOM from 'react-dom'; 
import { connect } from 'react-redux'; 
import PropTypes from 'prop-types'; 
import moment from 'moment'; 

import styles from './style.css'; 
import Arrow from './components/Arrow'; 
import RadioCheck from 'components/RadioCheck'; 
import Select from 'components/Select'; 
import DatePickerWrapper from 'components/DatePickerWrapper'; 
import { months } from 'utils'; 
import { changeMonth, changeFromDate, changeToDate, changeRadioDatepicker } from 'components/PostsPage/actions'; 

class DatePickerDropdown extends Component { 
    constructor(props) { 
     super(props); 
     this.firstChild = null; 

     this.state = { 
      open: false, 
      loadedPreferences: false, 
     }; 

     this._handleSelectedClick = this._handleSelectedClick.bind(this); 
     this._handleRadioChange = this._handleRadioChange.bind(this); 
     this._handleFromDatepickerChange = this._handleFromDatepickerChange.bind(this); 
     this._handleToDatepickerChange = this._handleToDatepickerChange.bind(this); 
     this._handleMonthChange = this._handleMonthChange.bind(this); 
     this._handleOutsideClick = this._handleOutsideClick.bind(this); 

    } 

    componentDidMount() { 
     window.addEventListener('click', this._handleOutsideClick, false); 
     setTimeout(() => { 
      this.loadPreferences(); 
     },5) 
    } 
    componentWillUnmount() { 
     window.removeEventListener('click', this._handleOutsideClick, false); 
    } 


    loadPreferences() { 
     const monthId = preferences.get(preferences.keys.DATEPICKER_MONTH); 
     const dateFrom = preferences.get(preferences.keys.DATEPICKER_FROM); 
     const dateTo = preferences.get(preferences.keys.DATEPICKER_TO); 
     const filterType = preferences.get(preferences.keys.DATEPICKER_FILTER_TYPE); 
     if (monthId !== null) { 
      this.props.changeMonth(monthId); 
     } 
     if (dateFrom !== null) { 
      this.props.changeFromDate(moment(dateFrom)); 
     } 
     if (dateTo !== null) { 
      this.props.changeToDate(moment(dateTo)); 
     } 
     if (filterType !== null) { 
      this.props.changeRadio(filterType); 
     } 
    } 
    getRange() { 
     const { datepickerFilter, month, dateFrom, dateTo} = this.props; 
     if (datepickerFilter === 'month') { 
      return { 
       start: moment().month(month).startOf('month').format('D. MMMM YYYY'), 
       end: moment().month(month).endOf('month').format('D. MMMM YYYY') 
      } 
     } 

     if (datepickerFilter === 'from_to') { 
      return { 
       start: dateFrom.format('D. MMMM YYYY'), 
       end: dateTo.format('D. MMMM YYYY'), 
      }; 
     } 
    } 

    toggleSelect(show = null) { 
     if (show !== null) { 
      this.setState(() => ({open: show})); 
     } 

     if (show === null) { 
      this.setState(() => ({open: !this.state.open})); 
     } 
    } 

    _handleSelectedClick() { 
     this.toggleSelect(); 
    } 

    _handleOutsideClick(e) { 
     if (!ReactDOM.findDOMNode(this).contains(e.target) && this.state.open) { 
      this.toggleSelect(false); 
     } 
    } 

    _handleFromDatepickerChange(date) { 
     if (this.props.dateFrom.toDate() !== date.toDate()) { 
      this.props.changeFromDate(date); 
      preferences.store(preferences.keys.DATEPICKER_FROM, date.toDate()); 
     } 
    } 

    _handleToDatepickerChange(date) { 
     if (this.props.dateTo.toDate() !== date.toDate()) { 
      this.props.changeToDate(date); 
      preferences.store(preferences.keys.DATEPICKER_TO, date.toDate()); 
     } 
    } 

    _handleMonthChange(month) { 
     if (this.props.month !== month) { 
      this.props.changeMonth(month); 
      preferences.store(preferences.keys.DATEPICKER_MONTH, month); 
     } 
    } 

    _handleRadioChange(filterType) { 
     if (this.props.datepickerFilter !== filterType) { 
      this.props.changeRadio(filterType); 
      preferences.store(preferences.keys.DATEPICKER_FILTER_TYPE, filterType); 
     } 

    } 

    render() { 
     const dropdownClass = this.state.open ? styles.dropdownActive : styles.dropdown; 
     const dropdownButtonClass = this.state.open ? styles.selectedActive : styles.selected; 
     const arrowClass = this.state.open ? styles.arrowActive : styles.arrow; 
     const range = this.getRange(); 
     return (
      <div className={styles.container}> 
       <div className={dropdownButtonClass} onClick={this._handleSelectedClick}> 
        <div className={styles.date}>{range.start}<span>to</span>{range.end}</div> 
        <div className={arrowClass}> 
         <Arrow up={this.state.open} size={10} invert={this.props.invert}/> 
        </div> 
       </div> 
       <div className={dropdownClass}> 
        <div className={styles.datepickerRow}> 
         <div> 
          <RadioCheck label={'Filter by Month'} type="radio" id="month" name="datepicker_radio" value="month" checked={this.props.datepickerFilter === 'month'} onChange={this._handleRadioChange}/> 
         </div> 
         <div className={styles.datepickerRowInner}> 
          <span>Month</span> 
          <div className={styles.inputItem}> 
           <Select 
            options={months} 
            onChange={this._handleMonthChange} 
            optionsToShow={12} 
            small 
            defaultOption={this.props.month.toString()} 
           /> 
          </div> 
         </div> 
        </div> 
        <div className={styles.datepickerRow}> 
         <div> 
          <RadioCheck label={'Filter by Date range'} type="radio" id="from" name="datepicker_radio" value="from_to" onChange={this._handleRadioChange} checked={this.props.datepickerFilter === 'from_to'}/> 
         </div> 
         <div className={styles.datepickerRowInner}> 
          <span>from</span> 
          <div className={styles.inputItem}> 
           <DatePickerWrapper date={this.props.dateFrom} onChange={this._handleFromDatepickerChange}/> 
          </div> 
         </div> 
        </div> 
        <div className={styles.datepickerRow}> 
         <div className={styles.datepickerRowInner}> 
          <span>to</span> 
          <div className={styles.inputItem}> 
           <DatePickerWrapper date={this.props.dateTo} onChange={this._handleToDatepickerChange}/> 
          </div> 
         </div> 
        </div> 
       </div> 
      </div> 
     ); 
    } 
} 

DatePickerDropdown.propTypes = {}; 
DatePickerDropdown.defaultProps = {}; 


const mapStateToProps = state => { 
    const { monthSelect, dateFrom, dateTo, datepickerFilter } = state.postsFilters; 
    return { 
     month: monthSelect, 
     dateFrom, 
     dateTo, 
     datepickerFilter 
    } 
}; 

const mapDispatchToProps = dispatch => { 
    return { 
     changeMonth: (monthId) => dispatch(changeMonth(monthId)), 
     changeFromDate: (date) => dispatch(changeFromDate(date)), 
     changeToDate: (date) => dispatch(changeToDate(date)), 
     changeRadio: (val) => dispatch(changeRadioDatepicker(val)), 
    } 
}; 

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(DatePickerDropdown); 

我想什么实现是从localStorage加载首选项。如果我在setTimeout()函数中调用了this.loadPreferences(),并延迟了100ms,它确实有效,但这并不合适。

我想这个问题源于我正在更新我映射到该组件的相同道具。什么是更好的方法来实现我的目标?

编辑:加入整个源,以避免混淆

回答

0

尝试显式绑定点击hanlder上下文this._handleOutsideClick.bind(本)

+0

感谢您的输入。但是,它包含在完整的代码中。我有目的地删除了代码中不重要的部分。我想我会把组件的整个源代码:) – IamLee

相关问题