When item added, DetailsList doesn't update
Asked Answered
S

2

6

I'm using office-ui-fabric-react library. Current version that I'm on is 7.17.0.

My list is super simple:

<DetailsList
    columns={this.state.columns}
    items={this.state.items}
    compact={true}
    selectionMode={SelectionMode.none}
    enableUpdateAnimations={true}
/>

When I change the items in a separate method (marked async) and do this.setState({items: someNewItems}), the list doesn't get re-rendered. I'm curious is this a known issue, or is the DetailsList needs to be handled in a special way?

To clarify, after executing this.setState nothing changes, but if I resize the page, the new elements appear suddenly.

Sap answered 2/8, 2019 at 21:57 Comment(2)
If you add console.log(this.state.items) on the render method, the changes are displayed?Grouper
Does that separate function have the correct this reference bound to it? ^ if you log the items and they don't change, try making your component's function an arrow function so it's bound to the component and can use this.setState.Sayles
S
4

This is due to shallow comparison, in fact the solution is listed in the documentation here: https://developer.microsoft.com/en-us/fabric#/controls/web/detailslist

From the docs:

My List is not re-rendering when I mutate its items! What should I do?

To determine if the List within DetailsList should re-render its contents, the component performs a referential equality check within its shouldComponentUpdate method. This is done to minimize the performance overhead associating with re-rendering the virtualized List pages, as recommended by the React documentation.

As a result of this implementation, the inner List will not determine it should re-render if the array values are mutated. To avoid this problem, we recommend re-creating the items array backing the DetailsList by using a method such as Array.prototype.concat or ES6 spread syntax shown below:

public appendItems(): void {
  const { items } = this.state;

  this.setState({
    items: [...items, ...['Foo', 'Bar']]
  })
}

public render(): JSX.Element {
  const { items } = this.state;

  return <DetailsList items={items} />;
}

By re-creating the items array without mutating the values, the inner List will correctly determine its contents have changed and that it should re-render the new values.

Sap answered 26/8, 2019 at 14:32 Comment(2)
I tried the solution and it doesn't work in my case. Anyone else got the same issue?Tranche
I spent a full afternoon on this - just couldn't figure out why it would not work - many thanks! Your answer helped me solve my issue!Windbroken
I
0

There is no issue with DetailsList. The table should update properly, as you indicated that when you resize the page the items show up but before that it doesn't. It's definitely because the render function isn't being called again.

Which means that when you do this.setState you are not updating the states of your present component. As Mirage, in the comments suggested try checking if you have the correct this and you are updating the correct component.

Iene answered 26/8, 2019 at 13:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.