James Gunn
James Gunn

Reputation: 389

React not reordering array of components on render

I am trying to render a list of components in order with react, the component is updating this array of elements but is not re-ordering them.

Pseudo code;

class Form extends Component {
  //
  // .... other initialization code and logic
  //

  updatePositions() {
    //
    // re-order this.state.page.page_contents
    //
    this.setState({ page: this.state.page });
  }

  renderContents() {
    return this.state.page.page_content.map((c, i) => {
      return (<ContentItem
        key={ i }
        content={ c }
      />);
    });
  }

  render() {
    return (
      <div className="row">
        <div className="medium-12 columns">
          { this.renderContents() }
        </div>
      </div>
    );
  }
}

If i log out the results of page.page_content the items are being reordered in the array, however the form render is not re-rendering the contents in its new order

Upvotes: 1

Views: 1476

Answers (4)

Delta Kapp
Delta Kapp

Reputation: 1232

You shouldn't be using array indices as keys if your array order is subject to change. Keys should be permanent, because React uses the keys to identify the components, and if a component receives a key that previously belonged to a different component, React thinks it is the same component as before.

Create unique keys for your elements that are permanent to those elements.

Upvotes: 1

Waseem Raja Shaik
Waseem Raja Shaik

Reputation: 343

renderContents() {
    return this.state.page.page_content.map((c, i) => {
      return (<ContentItem
        key={ i }
        content={ c }
      />);
    });
  }

it's your code here - key={i} i is not changing so it will not re-render the component - if you want to re-render the component - please make sure that - key should change.

renderContents() {
    return this.state.page.page_content.map(c => {
      return (<ContentItem
        key={ c }
        content={ c }
      />);
    });
  }

c is content - if it's change then Component will re-render

this.setState({ page: this.state.page }) it's wrong - ur trying to set the same value in same variable again .

class Form extends Component {
  //
  // .... other initialization code and logic
  //

  updatePositions() {
    //
    // re-order this.state.page.page_contents
    //
    this.setState({ page: newValueFromAPI.page });
  }

  render() {
    const { page: { page_content } } = this.state
    return (
      <div className="row">
        <div className="medium-12 columns">
          { page_content.length > 0 && (
             page_content.map(c => <ContentItem key={c} content={c}/>)
          )}
        </div>
      </div>
    );
  }
}

Upvotes: 0

bitten
bitten

Reputation: 2543

Don't mutate this.state, directly. Bring it into a new variable and then add it back into state.

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

from: https://reactjs.org/docs/react-component.html

Instead, you should try:

  updatePositions() {
    const page_contents = [...this.state.page.page_contents]
    // re order page_contents
    this.setState({ page: { page_contents });
  }

Upvotes: 0

Abdulla Thanseeh
Abdulla Thanseeh

Reputation: 10526

you could try to force update

 renderContents() {
          this.forceUpdate();           
          return this.state.page.page_content.map((c, i) => {
              return (<ContentItem
                key={ i }
                content={ c }
              />);
            });

          }

Upvotes: 0

Related Questions