使用redux-form中的<select>字段处理出生日期

时间:2018-02-18 15:57:28

标签: reactjs redux redux-form

我使用redux-form作为用户注册表单。 对于表单的出生日期部分,我有一个&lt; select&gt;日,月和年的字段。 到目前为止,我一直使用redux-form的Fields组件将每天,每月和每年作为单独的变量捕获: const dobSelects = fields =&gt; {   const {label,input} = fields;   回来(     &LT; DIV&GT;       &LT;标签&gt; {标号}&LT; /标签&gt;       &lt; select {... fields.day.input} name =&#34; dob&#34; ID =&#34;&#34;&GT;         &lt; option /&gt;         &lt; option value =&#34; 1&#34;&gt; 1&lt; / option&gt;         &lt; option value =&#34; 2&#34;&gt; 2&lt; / option&gt;         &lt; option value =&#34; 3&#34;&gt; 3&lt; / option&gt;       &LT; /选择&GT;       &lt; select {... fields.month.input} id =&#34;&#34;&gt;         &lt; option /&gt;         &lt; option value =&#34; january&#34;&gt; January&lt; / option&gt;         &lt; option value =&#34; 2月&#34;&gt; 2月&lt; / option&gt;         &lt; option value =&#34; march&#34;&gt; March&lt; / option&gt;       &LT; /选择&GT;       &lt; select {... fields.year.input} id =&#34;&#34;&gt;         &lt; option /&gt;         &lt; option value =&#34; 2000&#34;&gt; 2000&lt; / option&gt;         &lt; option value =&#34; 2001&#34;&gt; 2001&lt; / option&gt;         &lt; option value =&#34; 2002&#34;&gt; 2002&lt; / option&gt;       &LT; /选择&GT;     &LT; / DIV&GT;   ); }; 这会在我提交的值中产生以下内容: {day:&#34; 2&#34 ;, month:&#34; january&#34;,year:&#34; 2002&#34;} 但是,如果我想将一个字段作为Date对象而不是三个单独的字段发送,同时保持相同的用户界面,该怎么办? 我希望用户选择三个字段,而不是发送三个单独的字段,而是发送一个dateOfBirth字段作为Date对象。 此外,在这种情况下,redux-form的Fields组件似乎不够,因为我无法通过验证道具验证出生日期;我需要将这三个字段验证为一个而不是单独的。 如何用redux-form实现这一目标?

1 个答案:

答案 0 :(得分:3)

而不是使用Fields组件创建自定义字段。这是一般的想法:

class DOBSelects extends React.Component {
    constructor(props) {
        super(props);
        this.state = this.buildState(props.input.value)
    }

    componentWillReceiveProps(props) {
        if(props.input.value !== this.props.input.value) {
            this.setState(this.buildState(props.input.value));
        }
    }

    buildState(value) {
        return value ? { 
            date: value.getDate(), 
            month: value.getMonth() + 1, year: 
            value.getFullYear()
        } : {
            date: '',
            month: '',
            year: ''
        }
    }

    update(state) {
        this.setState(state);

        const { date, month, year } = { ...this.state, ...state };
        const { onChange, value } = this.props.input;

        if(date && month && year) {
            onChange(new Date(year, month - 1, date));
        } else if(value) {
            onChange(null);
        }
    }

    render () {
        const { label, input: { name } } = this.props;
        const { date, month, year } = this.state
        const thisYear = new Date().getFullYear();

        return (
        <div>
            <label htmlFor={name + '-day'}>
                {label}
            </label>
            <select onChange={e => { this.update({ date: e.target.value }); }} value={date} name={name + '-day'}>
                <option />
                {getOptions(1, 31)}
            </select>
            <select onChange={e => this.update({ month: e.target.value })} value={month} name={name + '-month'}>
                <option />
                {getOptions(1, 12)}
            </select>
            <select onChange={e => this.update({ year: e.target.value })} value={year} name={name + '-year'}>
                <option />
                {getOptions(thisYear - 20, thisYear)}
            </select>
        </div>
    );
  };
}

function getOptions(start, end) {
    const options = [];

    for(let i = start; i <= end; i++) {
        options.push(<option key={i}>{i}</option>)
    }

    return options;
}

更简单的解决方案是使用类似react-datepicker的内容。