0

I have the following method as part of one of my components in a react app.

renderDeducs() { var deducArray=[]; for(var x =0;x<this.props.deducciones.length;x++) { var deduc = this.props.deducciones[x]; deducArray.push(<tr key={x}> <td key={x.toString()+"nombre"}>{deduc.nombre}</td> <td key={x.toString()+"porciento"}>{deduc.porciento}</td> <td><button onClick={(e) => {this.delete(deduc.nombre)}}>Borrar</button> | <button>Editar</button> </td> </tr> ); } console.log(deducArray); return deducArray; } 

The idea is to be able to display the items of an array and provide a delete button for each item. The items are displayed inside an HTML table. However, the button for each row is deleting the last item in the array (the last row of the table). Apparently, even though "deduc" is a local variable and should be out of scope when the click events fire, deduc seems to have the value used in the last iteration of the loop. How can I tell each button what item of the array I want to delete?

EDIT:

here is the code for the "delete" method of the component and the constructor:

constructor(props) { super(props); this.state = { addMethod : this.props.addMethod, delMethod : this.props.delMethod }; this.renderDeducs = this.renderDeducs.bind(this); this.delete = this.delete.bind(this); } delete(nombre) { alert("Deleting " + nombre); this.state.delMethod(nombre); } 

As you can see, the actual delete from the array method happens on a method that is bound to a component higher up in the component tree (that how you you achieve the "single source of truth", isn't it?) On the parent component, this is what that method looks like:

delDeduction(nombre) { var stateArray = this.state.deducciones; for (var x =0;x<stateArray.length;x++) { if(stateArray[x].nombre === nombre) { stateArray.splice(x,1); this.setState({deducciones:stateArray}); return; } } 

}

3
  • Can you post the code for the delete function? Your code looks fine here, not sure why it would be getting the wrong value. Commented Mar 22, 2018 at 21:08
  • Is the first cell in the table different for each item? Does <td key={x.toString()+"nombre"}>{deduc.nombre}</td> render the right number? Commented Mar 22, 2018 at 21:09
  • Each "nombre" property is unique for every item. Commented Mar 23, 2018 at 1:58

2 Answers 2

2

Change code as:

Your problem is, deduc is defined as var, so deduc is hoisted inside the function. Then try to define it with let, it will prevent this behaviour.

renderDeducs() { var deducArray=[]; for(var x =0;x<this.props.deducciones.length;x++) { let deduc = this.props.deducciones[x]; deducArray.push(<tr key={x}> <td key={x.toString()+"nombre"}>{deduc.nombre}</td> <td key={x.toString()+"porciento"}>{deduc.porciento}</td> <td><button onClick={(e) => {this.delete(deduc.nombre)}}>Borrar</button> | <button>Editar</button> </td> </tr> ); } console.log(deducArray); return deducArray; } 

Info about javascript hoisting

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

1 Comment

Your answer works, too. I can only select one answer, but I will upvote for providing a solution that requires a minimal change!
1

You forgot to bind the handler.Also make sure to use the loop like below , it will make your life easy

renderDeducs() { return ( { this.props.deducciones.map(deduc => <tr> <td key={x.toString()+"nombre"}>{deduc.nombre}</td> <td key={x.toString()+"porciento"}>{deduc.porciento}</td> <td> <button onClick={this.deleteme.bind(this, deduc.nombre)}> Borrar </button> | <button>Editar</button> </td> </tr> ) } ); } deleteme(n){ let initial_val = this.props.deducciones.slice(); let obj_to_del= initial_val.find(d => d.nombre === n); initial_val.remove(obj_to_del); //update your state with the initial val } 

5 Comments

this.props is read only! this.props.deducciones=initial_val; won't work!
oops yes, I have been using mobx where I can do that, let me update the answer :)
You can wrap the component in React.Fragment to remove those nasty divs if you're using vs 16.2.
Just updating my code to use .map() made the whole thing work. Still not sure why my original code wasn't working though, since I did not change the onClick handler. I will update my question to post the full component code.
I think that was context problem

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.