0

I am creating input fields dynamically based on the number of object in my state array. Beside each field I am adding a button to remove that field. However, when the button is clicked it behaves in an unexpected way.

Below is the visual demonstration:

When I press "Remove Option" button on "Option 0":

here

The output is like :

this

However, when I see from console.log() the correct object is being removed. These are console.log() outputs before:

before

and after the above button click:

after

Here is how I loop from the array in my render():

const questions = this.state.values_array.map((question, index) => {


 return ( 
    <div key = {question.question_id}>   
    {this.state.options_array.map((option, i) => (
        option.questionID === question.question_id ? //to show only this question's options
          <div>
              <span>Option {i}:</span>
              <TextField type="text" defaultValue={option.description} />
              <span>Value:</span>
              <TextField type="number" defaultValue={option.value}/>
              <button onClick={() => this.removeOption(i)}>Remove Option</button>
          </div>
        :
          null
    ))}
    </div>
    )
  }

Here is my removeOption() method I am using to remove the input fields:

removeOption(index){

    let options = [...this.state.options_array];
    options.splice(index, 1);
    this.setState({ options_array: options });
}

And here is how I am calling it in my render's return:

 return (
   <div>{questions}</div>
)

3 Answers 3

1

The flaw of this approach is that in JavaScript, objects and arrays are reference types, so when we get an array, we actually get a pointer to the original array's object managed by react. If we then splice it, we already mutate the original data and whilst it does work without throwing an error, this is not really how we should do it, this can lead to unpredictable apps and is definitely a bad practice. A good practice is to create a copy of the array before manipulating it and a simple way of doing this is by calling the slice method. Slice without arguments simply copies the full array and returns a new one which is then stored. And we can now safely edit this new one and then update to react state with our new array. let me give you and example:

We have an array like this const arr=[1,2,3,4,5]. This is original array.

As I told you before, we can do that like this:

const newVar=arr.slice();
newVar.splice(Index,1);
console.log(newVar);

Or

An alternative to this approach would be to use it a ES6 feature, it is the Spread Operator

Our prior code can be something like this:

const newVar=[...arr]
newVar.splice(Index,1);
console.log(newVar);

That's it. Good luck

Sign up to request clarification or add additional context in comments.

Comments

0

You are missing the keys for the div containers. React needs to know which DOM Element has been removed so it re-renders it. Also, do not use the index of map as the key, instead use something like the id e.g. option.questionID.

Comments

0

you need to filter out the individual item from the list

removeOption(index) {
const options = this.state.options_array.filter((items, itemIndex) => itemIndex 
!== index)
this.setState({ options_array: options });}

Comments

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.