packages/react-examples/src/react/DetailsList/docs/DetailsListBestPractices.md
In addition to creating column headers, DetailsList also allows the manual definition of row headers. In the example below, the Name column has been specified as a row header using isRowHeader: true. When creating a DetailsList where one column is clearly the primary label for the row, it's best to use isRowHeader on that column to create a better screen reader experience navigating the table. For selectable DetailsLists, specifying a row header also gives the checkboxes a better accessible label.
If using onItemInvoked in DetailsList, be sure to add an element (such as a button or link) within the row's cell content that does the same thing, to ensure assistive tech such as voice control or screen readers can perform the action.
DetailsList supports different selection modes with keyboard behavior differing based on the current selection mode.
isSelectedOnFocus is a prop that, when set to false, alters DetailList's selection behavior.
Add the data-is-scrollable="true" attribute to your scrollable element containing the DetailsList.
By default, the List used within DetailsList will use the body element as the scrollable element. If you contain the List within a scrollable div using overflow: auto or scroll, the List needs to listen for scroll events on that element instead. On initialization, the List will traverse up the DOM looking for the first element with the data-is-scrollable attribute to know which element to listen to for knowing when to re-evaulate the visible window.
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 associated 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(): JSXElement {
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 it should then re-render with the new values.