1
votes

I am building a list of child elements from an array in Parents state. I can pass information from the child back to the parent, and update the parent's state.

However, when I try and reorder the objects in the array (to change the order of the children in the DOM), it changes the order of the array in Parents state, but does not update their location in the dom when it re-renders.

To recap:

  • it DOES re-render both the parent and the children
  • it DOES change the order of the objs in this.state.array
  • it DOES NOT reorder the child components in the DOM.

My understanding is that it re-renders, and re-iterates through my list. If I push new items to the end of my array, it will render the new items on re-render, but does not move items i've moved within the array using the splice.

Here is a quick snippit to try and show how I have it structured:

class Parent extends Component {
  constructor(props) {
    super();
    this.state = {
      array: [{obj1}, {obj2}, {obj3}]
    }
    this.moveChild = this.moveChild.bind(this);
    this.updateChild = this.updateChild.bind(this);
  }

  moveChild(obj) {
    //this moves the item left in the array
    //obj is state of child passed from child
    let index = obj.index;
    if (index-- < 0) {
      index = 0;
    }
    this.setState((prevState, props) => {
      return this.state.array.splice(index, 0, this.state.array.splice(obj.index, 1)[0]);
    });
  }

  updateChild(obj) {
    //updates the state of parent with changes of child.
  }

  render() {
      return ({
            this.state.array.map((item, i) =>
              <
              Child key = {i}
              updateChild = {this.updatechild}
              moveChild = {this.moveChild}
              item = {item}
              /> );}
  }
}

class Child extends Component {

//has its own state which tracks several parameters.

//has function to pass its state to parent using updateChild

//has function to pass a move operation back to parent

    render() {
        return ( 
          <button onClick = {this.moveChildFun} > Move < /button> 
          <button onClick = {this.updateChildFun} > Updates < /button>
        );
    }
}
1

1 Answers

1
votes

You shouldn't use array indexes as list keys in react. Use business keys instead. For example when your items objects look like:

const array = [{ id: 1, value: 'a' }, { id: 2, value: 'b' }, ...]

You can use id as a key:

<Child key={item.id}
  updateChild={this.updatechild}
  moveChild={this.moveChild}
  item={item.value}
/>

You can find more about lists and keys in official documentation