2017-09-16 24 views
0

Ich habe versucht, eine Aktion in componentDidMount zu schicken, leider bin ich immer:Reagieren Aktion in componentDidMount Dispatching()

Maximale Call-Stack Größe

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); 

überschritten Was ich versuche zu erreichen ist es, Präferenzen von localStorage zu laden. Wenn ich den Aufruf von this.loadPreferences() in einer setTimeout() mit einer Verzögerung von 100ms umschlinge, funktioniert es zwar, aber das fühlt sich nicht richtig an.

Ich denke, das Problem rührt von der Tatsache her, dass ich die gleichen Requisiten aktualisiere, die ich auf diese Komponente abbilde. Was wäre ein besserer Ansatz, um mein Ziel zu erreichen?

EDIT: hinzugefügt ganze Quelle Verwirrung

Antwort

0

Versuchen Sie zu vermeiden, explizit zu binden klicken hanlder zu Kontext this._handleOutsideClick.bind (this)

+0

Vielen Dank für die Eingabe. Dies ist jedoch im vollständigen Code enthalten. Ich habe absichtlich unwichtige Teile des Codes entfernt. Ich denke, ich werde den gesamten Quellcode der Komponente einfügen :) – IamLee

Verwandte Themen