我一直试图在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 :(得分:0)
尝试将click hanlder显式绑定到context this._handleOutsideClick.bind(this)