2

I have a rather tricky question to ask, I'm working on a page that accepts several inputs from the Data-Base and with that I'm generating several inputs( the number of inputs is not constant)

basically like this:

 const form = this.state.inputs.map((input, i) => {
      if (input) {
        return (
          <div key={i}>
            <div>
              <label htmlFor={input.inputLabel}>{input.inputName}</label>
            </div>
            <div className="form-input">
              <input
                name={`${input.inputName}-${i}`}
                type={input.inputType}
                id={input.inputLabel}
                onChange={this.onChange}
              />
            </div>
          </div>
        );
      }
    });

after generating the form with the unknown number of values ( depends on the Data-Base) I want to save all the values of that form, but because I do not know the number of inputs I made 2 arrays ( I need to save the value and the name to be later shown in a different page)

  state = {
  ....
    inputData: {
      names: [],
      values: []
    }
  ....
  };

but I'm having trouble of actually saving the values in the setState

 onChange = e => {
    e.preventDefault();
    const { name, value } = e.target;
    var nameIndex = name.split('-');
    const names = [];
    const values = [];
    values[nameIndex[1]] = value;
    names[nameIndex[1]] = nameIndex[0];
    const inputData = { names, values };
    this.setState({ inputData });
  };

the setState works like this: on my map I give each input a name that contains the index that's generated by the map so the name is like "inputname-1", and I use split to take out the 1 and update the two arrays I did in the setState (values,names) and everytime the user writes in the input it changes the value inside the array like so: values[1]=(users input...) , but I noticed that if I change the 2nd value for example, the values before him in the index 1 and 0 become undefined, am I missing something?

4
  • instead of const names = []; const values = []; do const names = this.state.inputData.names; const values = this.state.inputData.values Commented Feb 11, 2019 at 17:23
  • 1
    but that means I will be changing the state directly , am I wrong? Commented Feb 11, 2019 at 17:25
  • I don't think so. just change const to var it would be better Commented Feb 11, 2019 at 17:27
  • @evgeni fotia, I think it does, and const var doesn't change anything, I'm not changing the binding of the value, just the context. EDIT: I'm 100% sure it's wrong, if you assign a=[1,2,3] and b=a and b[1]=9, it will change the a array, so what you suggested is directly changing the state and its wrong. Commented Feb 11, 2019 at 17:29

1 Answer 1

3

You are creating a new names and values array with just one index populated in it. This is why you are overwriting other indices in the array

You could do something like this if you want to update only the specific indexes without mutation:

const { name, value } = e.target;
const [key, index] = name.split('-');

this.setState(prevState => ({
   ...prevState,
   inputData: {
      values: Object.assign([], {...prevState.inputData.values }, { [index]: value }),
      names: Object.assign([], {...prevState.inputData.names }, { [index]: key })
   }
}))

Another option is to take a copy of the prevState.inputData.values using the spread syntax and update it's value at specific index and then set it to inputData:

const { name, value } = e.target;
const [key, index] = name.split('-');

this.setState(prevState => {
  const cloneValues = [...prevState.inputData.values],
        cloneNames = [...prevState.inputData.names];

  cloneValues[index] = value;
  cloneNames[index] = key;

  return {
    ...prevState,
    inputData: {
      values: cloneValues,
      names: cloneNames
    }
  }
})
Sign up to request clarification or add additional context in comments.

8 Comments

I'm sorry I don't understand how that part works, "[index]: value" , could you explain to me please?
@AlexK does either my solution work? I'll add an explanation for Object.assign
the first solution does not compile, and quite frankly I don't understand it, I do know how object assign works.
@AlexK sorry about that. Forgot to add some brackets {}. Updated now. I think second solution is much more straight forward and should work
@AlexK you got it. Spreading an array within a flower brackets {...array } creates an object with indexes as keys and each value as value. Then you merge this object with another object which your index to be updated as key. This repaces the key in the spread object. Object.assign is usually used to merge objects. But, when used with Object.assing([], someObject), the keys of that object become the indices in the array.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.