So I am practicing React and wanted to display a "Arya's kill list" ], I wanted to make it possible to update it. So in my ToKill component when you double click on a character it shows inputs with values. But it is not possible to update them.

I wrote a function in my main App component it looks like this :

    const toKillPpl = { ...this.state.toKill }
    toKillPpl[index] = updatedToKill
      this.setState({ toKillPpl })
  } 

next I pass it to ToKillList component with a state :

            doubleClick = {this.doubleClickHandler}
            deleteToKill = {this.deleteToKillHandler}
            backBtn = {this.backBtnHandler} 
            state = {this.state}
            toKillState = {this.state.toKill}
            update = {this.toKillUpdate}
          /> 

in my ToKillList component I map over my state and I pass this function with a state of a person (toKillPerson) :

const ToKillList = (props) => props.state.toKill.map((toKill, index) => {
  return <ToKill 
    double ={() => props.doubleClick(index)}
    formDouble={toKill.formDouble}
    click ={() => props.deleteToKill(index)}
    backBtn ={() => props.backBtn(index)}
    key={index + toKill.name}
    index={index}
    toKillPerson ={props.toKillState[index]}
    update={props.update}
    name={toKill.name}
    cause={toKill.cause}
    img={toKill.img} 
    />
  })

Finally in my ToKill component I write a function "handleChange" :

handleChange = (e) => {
    const updatedToKill = {
        ...this.props.toKillPerson,
        [e.currentTarget.name]: e.currentTarget.value
    }
    this.props.update(this.props.index, updatedToKill)
}

And here are inputs:

<input 
      type="text"
      name="name"
      className="hero-name" 
      onChange={this.handleChange} 
      value={this.props.name}
   />
<input 
      type="text"
      name="img"
      onChange={this.handleChange} 
      value={this.props.img}
   />
<input 
      type="text"
      name="cause"
      className="hero-cause" 
      onChange={this.handleChange} 
      value={this.props.cause}
   />

And it doesn't work. Is it a good approach, or I messed it up completely?

In case I wasn't clear here is a github repo: https://github.com/jakubmas/Aryas-Kill-List

2 Answers

1
tarzen chugh On

Two correction in update method in your code.

1) You are not correctly copying over object,

const toKillPpl = { ...this.state.toKill }

This creates a shallow copy, you need deep cloning for this. You could either use JSON.strigify or lodash deepClone method.

2) You are not updating toKill state which is being passed to child components.

Here is the updated method:

  toKillUpdate = (index, updatedToKill) => {
    // const toKillPpl = JSON.parse(JSON.stringify(this.state.toKill)); // use this
    const toKillPpl = _.cloneDeep(this.state.toKill); // or this
    toKillPpl[index] = updatedToKill;
    this.setState({ toKill: toKillPpl });
  };

Here is the working codesandbox link

Hope that helps!!!

0
vlin On

Another way to do this is that you could import immutability-helper (https://github.com/kolodny/immutability-helper), and use it to update state.toKill without mutating it:

import update from 'immutability-helper';

// Assuming 'updateToKill' input is an object...
handleUpdate = (index, updatedToKill) => {
    this.setState(prevState => ({
        toKill: update(prevState.toKill, {
            [index]: {
                $set: updatedToKill,
            },
        }),
    }));
};