Reputation: 268
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
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
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
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
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