score:3

Accepted answer

when you update the display value of the inputs in state, you need to use this.setstate to change the state data and cause a re-render with the new data. using input.key = value is not the correct way.

using state correctly
there are three things you should know about setstate().

do not modify state directly
for example, this will not re-render a component:

// wrong
this.state.comment = 'hello';
instead, use setstate():

// correct
this.setstate({comment: 'hello'});
the only place where you can assign this.state is the constructor.

read more from facebook directly here

i would actually suggest a little bit of a restructure of your code though. it's not really encouraged to have components as part of your state values. i would suggest having your different inputs as data objects in your this.state.inputs, and loop through the data and build each of the displays that way in your render method. like this:

suppose you have one input in your this.state.inputs (and suppose your inputs is an object for key access):

inputs = {
    1: {
        selectedtime: 0:00,
        selectedvalue: 2
    }
}

in your render, do something like this:

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

notice how we're binding the key on the onchange, so that we know which input to update. now, in your onchange function, you just set the correct input's value with 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 }))

    })
}

this isn't tested, but basically this immutable statement is going to make a copy of this.state.inputs and set the selectedtime value inside of the object that matches the key, to the event.target.value. state is updated now, a re-render is triggered, and when you loop through the inputs again in the render, you'll use the new time value as the timevalue to your component.

again, with the object.assign edit, it isn't tested, but learn more [here]. 2 basically this statement is merging a new timevalue value in with the this.state.inputs[key] object, and then merging that new object in with the entire this.state.inputs object.

does this make sense?

score:0

i modified the onchange in the 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)
    });
}

the key points are:

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

having thought about it though, input is an object reference to the input in the this.state.inputs so actually [...this.states.inputs] would have been enough??


Related Query

More Query from same tag