NoobCoder
NoobCoder

Reputation: 127

React event.target.value is retuning undefined

I am trying to delete a record when the user clicks on it.

The list shown to the screen would be something like:

Sarah funds job
John loans Barry
Tom funds Ellie

So above, that's what the user will see and in the state, it's structured like

state = {
    transactionInputs: [
        {id: 1, xParty: "Paul", yAction: "Funds", zParty: "Leon"},
        {id: 2, xParty: "Jerry", yAction: "Loans", zParty: "Tom"},
        {id: 3, xParty: "Sarah", yAction: "Repays", zParty: "Alex"},
    ],

In the parent component, below is how I'm calling and displaying the data. And you can see I am passing in deleteItem method, that is shown below too.

    <div className={classes.resultborder}>
            {this.state.transactionInputs.map(data => {
                return (
                    <Inputs
                        key={data.id}
                        xParty={data.xParty}
                        zParty={data.zParty}
                        yAction={data.yAction}
                        deleteItem={this.deleteItem}/>
                );
            })}
        </div>

And the deleteItem function below.

deleteItem = event => {
    const newState = [...this.state.transactionInputs];
    newState.splice(event.target.value, 1);
    this.setState({transactionInputs: newState})
}

Right now in the child component called Inputs, we are just returning...

<div>
    <p className={classes.InputLayout} onClick={props.deleteItem}>
       {props.xParty} {props.yAction} {props.zParty}</p>
</div>

The user will see the xParty, yAction and zParty, I have also passed in the deleteItem function we created in the parent component and it's set on the onClick.

Now, that's the relevant code, the issue I am having is that in my deleteItem function, the event.target.value is undefined, I'm not sure if there's something I don't understand OR it's just a bug.

Upvotes: 0

Views: 3527

Answers (1)

Drew Reese
Drew Reese

Reputation: 202605

The convention would be to pass a unique value like the id to the delete callback.

deleteItem={() => this.deleteItem(data.id)}

And then filter on that id in the callback.

deleteItem = id => {
  const newTransactionInputs = this.state.transactionInputs.filter(t => t.id !== id);
  this.setState({transactionInputs: newTransactionInputs})
}

transactionInputs.filter(t => t.id !== id) returns a new array with all transactions that have an id that doesn't match the one you want removed.

[EDIT to address secondary question regarding callbacks]

I'm new to React and ES6 really. deleteItem={() => this.deleteItem(data.id)} The syntax for this does confuse me. we are doing '() =>' but why are we creating an anonymous function to call a function we have made?

Well, there's really two things at work here, (1) callbacks and (2) function signatures.

It appears you understand the callback part, I'll try to explain the signature part. With a component or element like <div onClick={callback} /> what's happening is the onclick handler calls the specified callback with that event directly as the first parameter, like callback(event). This is nearly equivalent to <div onClick={(event) => callback(event)} />, which is just a function that receives the event then calls the callback. If the signature of the callback function matches (i.e. it has a named parameter, it'll accept it).

In our case we don't care about the event object, but we want to pass a parameter, <div onClick={() => callback(newParameter)} >. <div onClick={callback(newParameter)} > won't work since you know the callback would be invoked right away, so we have to wrap it in a function. It should be noted that sometimes your code may care about the event (such as on forms) where you want to prevent the default form action from firing.

clickHandler = (e, data) => {
  e.preventDefault();
  callback(data);
}

<div onClick={event => clickHandler(event, data)} />

Upvotes: 1

Related Questions