简体   繁体   中英

Deleting component from array of Components

I'm new to react and only understand the basic. I got this project from someone to look at, but I'm scratching my head since morning on how the deletePersonHandler function works and how is he passing index as a prop and then accessing that prop in the Person component, and by clicking on a component he can delete the specific component. Please if you can try to try to go over it in easy but in under the hood way.Your help would be really appreciated.

App Component

class App extends Component {
  state = {
    persons: [
      { id: 'asfa1', name: 'Max', age: 28 },
      { id: 'vasdf1', name: 'Manu', age: 29 },
      { id: 'asdf11', name: 'Stephanie', age: 26 }
    ],
    otherState: 'some other value',
    showPersons: false
  }

  nameChangedHandler = ( event, id ) => {//some other function}

  togglePersonsHandler = () => {//some other function}

  deletePersonHandler = (personIndex) => {
    const persons = [...this.state.persons];
    persons.splice(personIndex, 1);
    this.setState({persons: persons});
  }

  render () {
    const style = {
       //some css styling
    };

    let persons = null;

    if ( this.state.showPersons ) {
      persons = (
        <div>
          {this.state.persons.map((person, index) => {
            return <Person
              click={() => this.deletePersonHandler(index)}
              name={person.name} 
              age={person.age}
              key={person.id}
              changed={(event) => this.nameChangedHandler(event, person.id)} />
          })}
        </div>
      );
    }

    return (
      <div className="App">
        <h1>Hi, I'm a React App</h1>
        <p>This is really working!</p>
        <button
          style={style}
          onClick={this.togglePersonsHandler}>Toggle Persons</button>
        {persons}
      </div>
    );

  }
}

Person Component

const person = ( props ) => {
    return (
        <div className="Person">
            <p onClick={props.click}>I'm {props.name} and I am {props.age} years old!</p>
            <p>{props.children}</p>
            <input type="text" onChange={props.changed} value={props.name} />
        </div>
    )
};

Ok so you have two questions if I understand it well:

  1. How can he delete the person on click?
  2. How does deletePersonHandler work?

So.

  1. The person is deleted by calling deletePersonHandler from the person component. This is specified by that click={() => this.deletePersonHandler(index) (also click={() ... has to be rather onClick={() ... !). So if somebody clicks on the Person, it will call the deletePersonHandler with the person index as an argument. This will delete the person as this method says.

  2. How does it delete the preson? Ok, line by line:

This is the method definition with name and arg personIndex which sould be the number of the person.

deletePersonHandler = (personIndex) => {

he defines constant persons from the state of the component

const persons = [...this.state.persons];

he splices one element at personIndex from the array ( splice() )

persons.splice(personIndex, 1);

and he sets the new state of the component from the spliced array

this.setState({persons: persons});

after setting a new state, the App component is rerendered but with only two persons in state after deleting one.

React docs:
State and Lifecycle - React
Handling Events - React

Please read the code comments below. For a step-by-step explanation. This really comes down to understanding a few basic JavaScript constructs:

  1. Rest Parameters : the ... says grab an unknown number of elements and store them into an array. (NOTE: the use of const persons is completely acceptable - previous answer is incorrect)

    • It could also be written const persons = this.state.persons
  2. Array.prototype.splice(startIndex, deleteCount) : Given an index to start deleting and an index to stop deleting, this method removes elements from an array. Since " deleteCount " is 1, it will delete one element from the array. That element is the index of the persons clicked upon.

  3. Array.prototype.map : This is an iterator that runs a function against each element of an array. So in the render() method this code: this.state.persons.map((person, index) iterates over each person and creates the Person component for each person stored in the Class' persons array. Note the index for each person is passed into the map() method. So the click handler then passes the individual index for the clicked upon person to the deletePersonHandler() method on the App component. That that is how it knows which person to delete.

You can find a working example of this code for your review and understanding here: https://codesandbox.io/s/3084w8rjk6

deletePersonHandler = personIndex => {
  // This says "Create a local variable and assign to the list of persons registered on this class"
  const persons = [...this.state.persons];
  // This says "Use the Integer passed in to this function as personIndex as the starting point in the array,
  // and splice (remove elements from the array starting there for 1 element" (remove the person from the array);
  persons.splice(personIndex, 1);
  // Components have a setState() method, this overwrites the Class' persons state with the local version
  this.setState({ persons: persons });
  // React renders the new persons state into the view
};

So really what it comes down to, is the person is taking advantage of some cool features that ES6 provides. Let's step through the two important parts:

Part 1 The first important piece here is the map function, which creates an array of Person components from the original persons array

{this.state.persons.map((person, index) => {
            return <Person
              click={() => this.deletePersonHandler(index)}
              name={person.name} 
              age={person.age}
              key={person.id}
              changed={(event) => this.nameChangedHandler(event, person.id)} />
          })}

The map function has some built in features provided by the JavaScript language. One of those features is providing an index parameter, which tracks the current index you are at in the array while looping through each element. So when you see:

(person, index)

the person is using that built in feature to attach an integer value to each Person component.

This is important, because they are using this integer value, to keep track of that specific persons index in the persons array you are storing in state. The other important piece inside this map function, is this:

click={() => this.deletePersonHandler(index)}

Each Person Component also gets created with an an inline function with its index already hardcoded into the parameter for the deletePersonHandler function. When the deletePersonHandler function is invoked from within a specific Person, the deletePersonHandler already knows exactly what element from the array should be removed, because of the index hardcoded into it.

Part 2 Lets go over what is happening inside of deletePersonHandler:

deletePersonHandler = (personIndex) => {
    const persons = [...this.state.persons];
    persons.splice(personIndex, 1);
    this.setState({persons: persons});
}

First, they are creating a copy of the persons array, in order not to work on the actual persons array stored in state, which is just good practice. They do that, by taking advantage of the ES6 spread operator , which you can read up on by clicking the link.

Second, using the hardcoded integer index passed as a parameter from the previous map function, they use the splice method, to delete that element from the newly created array.

persons.splice(personIndex, 1)

The first parameter is self explanatory, but the second one, just says, "I want to delete only this 1 element".

After that's done, its simple as setting that newly created array to replace the original persons array in state.

Here is a codepen for you to mess around with. Make sure to uncomment some of the console.logs, so you can see what is happening. Its just some fancy JavaScript at the end of the day, nothing very React specific.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM