动态创建自定义表单组件

时间:2016-11-23 22:10:50

标签: javascript reactjs

有关完整图片,请参阅此gist

基本上我会有这种形式:

form

单击加号时,应显示另一行,其中包含日期和时间字段的下拉列表。

我可以创建代码来向表单添加输入,但是我遇到了单个组件(selectTimeInput是一行)实际更新其值的问题。

onChange中的MultipleDayTimeInput正在接收正确的数据,它只是未更新的显示。我非常新的反应所以我不知道是什么导致显示器不更新....

我认为这是因为SelectTimeInput渲染函数没有被调用,因为传入的props没有被更新,但我不确定实现它的正确方法。

考虑到这一点,是否需要在setState的{​​{1}}中调用onChange,并且需要从MultipleDayTimeInput删除已更改的输入并重新读取为了迫使渲染器射击......这对我来说似乎有点笨拙......

2 个答案:

答案 0 :(得分:3)

更新状态输入的显示值时,需要使用this.setState更改状态数据并使用新数据重新渲染。使用input.key = value不是正确的方法。

  

正确使用国家
  你应该知道三件事   的setState()。

     

不要直接修改状态
  例如,这不会重新渲染a   成分:

     

//错了   this.state.comment ='你好';
  相反,使用setState():

     

//正确
  this.setState({comment:' Hello'});
  你唯一的地方   可以指定this.state是构造函数。

直接从Facebook阅读更多内容here

我实际上会建议你对代码进行一些重组。我们并不鼓励将组件作为您的州值的一部分。我建议在this.state.inputs中将不同的输入作为数据对象,并循环遍历数据并在render方法中构建每个显示方式。像这样:

假设你的this.state.inputs中有一个输入(假设你的输入是密钥访问的对象):

inputs = {
    1: {
        selectedTime: 0:00,
        selectedValue: 2
    }
}

在渲染中,执行以下操作:

render() {
    let inputs = Object.keys(this.state.inputs).map((key) => {
        let input = this.state.inputs[key]
        return (<SelectTimeInput
            key={key}
            name={'option_' + key}
            placeholder={this.props.placeholder}
            options={this.props.options}
            onChange={this.onChange.bind(this, key)}
            timeValue={input.selectedTime}
            selectValue={input.selectedValue} 
         />)      
    )}
    return (
        <div>
            <button className="button" onClick={this.onAddClick}><i className="fa fa-plus" /></button>

            { inputs }
        </div>
    );
}

注意我们如何在onChange上绑定密钥,以便我们知道要更新的输入。现在,在您的onChange函数中,您只需使用setState设置正确的输入值:

onChange(event, key) {
    this.setState({
        inputs: Immutable.fromJS(this.state.inputs).setIn([`${key}`, 'selectedTime'], event.target.value).toJS()

        // or
        inputs: Object.assign(this.state.inputs, Object.assign(this.state.inputs[key], { timeValue: event.target.value }))

    })
}

这个没有经过测试,但基本上这个Immutable语句将复制this.state.inputs并将匹配键的对象内的selectedTime值设置为event.target.value。状态现在更新,触发重新渲染,当您在渲染中再次循环输入时,您将使用新的时间值作为组件的timeValue

再次,使用Object.assign编辑,它没有经过测试,但了解更多[此处]。 2这个语句基本上是将一个新的timeValue值与this.state.inputs [key]对象合并,然后将该新对象与整个this.state.inputs对象合并。

这有意义吗?

答案 1 :(得分:0)

我修改了onChange中的MultipleDayTimeInput

onChange(event) {
    const comparisonKey = event.target.name.substring(event.target.name.length - 1);
    const input = this.getInputState(comparisonKey);

    input.selected = event.target.value;
    input.display = this.renderTimeInput(input);

    let spliceIndex = -1;
    for (let i = 0; i < this.state.inputs.length; i++) {
        const matches = inputFilter(comparisonKey)(this.state.inputs[i]);

        if (matches) {
            spliceIndex = i;
            break;
        }
    }

    if (spliceIndex < 0) {
        throw 'error updating inputs';
    }

    this.setState({
        inputs: [...this.state.inputs].splice(spliceIndex, 1, input)
    });
}

关键点是:

// re render the input
input.display = this.renderTimeInput(input);

// set the state by copying the inputs and interchanging the old input with the new input....
this.setState({
    inputs: [...this.state.inputs].splice(spliceIndex, 1, input)
});

考虑到这一点,input是对this.state.inputs输入的对象引用,所以实际上[...this.states.inputs]已经足够了吗?