Diego
Diego

Reputation: 268

React App - removing dynamically-created TextInput always removes the last in the array

I am dynamically-creating controlled TextInputs successfully. For each TextInput created, a 'remove' button is also created which, on trigger, should remove that specific TextInput from the array. However it always removes the last TextInput in the array instead. Here is the remove function which is defined in the parent component:

   removeCertClick = (i) => {
    let certifications = [...this.state.certifications];
    certifications.splice(i, 1);
    this.setState({ certifications });
   }

My initial state:

this.state = {
   certifications: [{ certification: '' }]
}

Here is my code to dynamically render the TextInputs along with the remove button:

renderCertificationFields = () => {
    const { certifications } = this.props.values;
    const { handleCertificationChange } = this.props; //receiving as props from parent component

    return certifications.map((item, index) => (
        <Grid container spacing={1} key={index}>    
            <Grid item md={10}>
                <TextField
                    label='Certification name'
                    name='certification'
                    onChange={(index, event) => handleCertificationChange(index, event)}
                    defaultValue={item.certification || ''}
                />
            </Grid>
            <Grid item md={2}>
                <Button
                    onClick={() => removeCertClick(index)}
                >Remove</Button>
            </Grid>
        </Grid>
    ))
}

I appreciate any help.

Upvotes: 1

Views: 46

Answers (4)

Diego
Diego

Reputation: 268

The remove function is indeed correct. The problem was arising due to I was forgetting to add the "value" property for TextField like so:

<TextField
                label='Certification name'
                name='certification'
                onChange={event => handleCertificationChange(index, event)}
                value={item.certification} // prop that was missing
            />

I appreciate all your guys answers as it helped me figure this out.

Upvotes: 0

vicacid
vicacid

Reputation: 537

Your removeCertClick function should act like you want. Try to log i var there and check element index.

 removeCertClick = (i) => {
    console.log('remove', i);
    let certifications = [...this.state.certifications];
    certifications.splice(i, 1);
    this.setState({ certifications });
   }

If you see index you expect - problem is not here.

Upvotes: 1

Vivek Doshi
Vivek Doshi

Reputation: 58563

As per your code, there is no issue, it should work perfectly fine,

I think due to same name or kind of that you are misunderstanding like its removing always last :


You can see that in below snippet by runing code snippet :

const { useState , useEffect } = React;

class App extends React.Component {
  
  state = {
    certification : ["Cert 1","Cert 2","Cert 3","Cert 4","Cert 5","Cert 6","Cert 7","Cert 8"]
  }
  
  removeCertClick = (i) => {
    let certification = [...this.state.certification];
    certification.splice(i,1)
    this.setState({certification})
  }


  render() {
    return (
      <div>
        With Name :
        <br/><br/>
        {
          this.state.certification.map((crt,i) => <button onClick={() => this.removeCertClick(i)}>{crt} - X</button>)
        }
        <br/><br/>
        Button Name With Index : (Looks like you are removeing last always) :
        <br/><br/>
        {
          this.state.certification.map((crt,i) => <button onClick={() => this.removeCertClick(i)}>Remove {i}</button>)
        }
      </div>
    );
  }
  
}

ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>

Upvotes: 1

EugenSunic
EugenSunic

Reputation: 13703

This is how you need to do it, use filter to avoid copying the array and filter all the elements which do not contain the given index, by that you'll remove the wanted element

 removeCertClick = (i) => {
   const certifications = this.state.certifications.filter((x, j) => i !== j);
   this.setState({
     certifications
   });
 }

Upvotes: 0

Related Questions