React.js: Set sticky table-header cell width based on corresponding table-row cell width

You can get the widths of your table cells by querying for them after rendering. To access a React component after rendering, we'll need to use a ref.

constructor(props) {
  ...
  this.bodyRef = React.createRef()
}

Pass it as a prop to the table body.

<tbody
  ...
  ref={this.bodyRef}
>

Then you can access it after rendering in componentDidMount. If you remove, add or edit rows you may want to do it in componentDidUpdate as well (but be careful not to make an infinite loop).

componentDidMount() {
  const row = this.bodyRef.current.children[0].children; // Get the children of one <tr>
  // the path from this.bodyRef.current to the children you need may vary.
  const headerWidths = [];
  for (let i = 0; i < row.length; i += 1) {
    headerWidths.push(row[i].getBoundingClientRect().width); // Get the rendered width of the element.
  }
  this.setState({
    headerWidths
  });
}

Then just use the width values in your state.

constructor(props) {
  ...
  this.state = {
    ...
    headerWidths: []
  }
}
...
render() {
  return (
    ...
    <th style={{ width: this.state.headerWidths[index] }}>
      ...
    </th>
  )
}

Here's a working version of your handy example.

Edit React Sticky Table-Header


I'm using react-sticky-table because I need an easy way to create a table with a freezable header and columns. You can't set the width of the cell using width but you can use max-width and min-width as a workaround, which is what I'm doing, to set the cell width. E.g.:

React/JS file:

<Cell className='sticky-table-cell'>
    ...

CSS file:

.sticky-table-cell{
      display: table-cell;
      min-width: 400px;
      max-width: 400px;
      white-space: pre-wrap;
    }

pre-wrap makes sure that the text inside the cell breaks according to the available width.