table: useFlexLayout plugin hook error

V7 I’m not sure if I am doing something wrong with the configuration of the useFlexLayout plugin but using it gives the following error: Cannot read property 'columns' of undefined

I am using the plugin as shown below.

  const { getTableProps, headerGroups, rows, prepareRow } = useTable({
    columns,
    data,
  },
  useFlexLayout
  )

This error occurs in version 7.0.0-alpha.13 and above

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 17 (8 by maintainers)

Most upvoted comments

If you urgently need it here’s my updated version, works pretty much the same as the old one and is compatible with alpha.19. Since @tannerlinsley mentioned potential deprecation I guess it can be useful in the future.

import PropTypes from 'prop-types';

function sum(arr) {
  return arr.reduce((prev, curr) => prev + curr, 0);
}

function getFirstDefined(...args) {
  for (let i = 0; i < args.length; i += 1) {
    if (typeof args[i] !== 'undefined') {
      return args[i];
    }
  }
  return undefined;
}

function getSizesForColumn({ columns, id, width, minWidth, maxWidth }, defaultFlex) {
  if (columns) {
    columns = columns
      .filter(col => col.show || col.visible)
      .map(column => getSizesForColumn(column, defaultFlex))
      .filter(Boolean);

    if (!columns.length) {
      return false;
    }

    const flex = sum(columns.map(col => col.flex));
    const width = sum(columns.map(col => col.width));
    const maxWidth = sum(columns.map(col => col.maxWidth));

    return {
      flex,
      width,
      maxWidth
    };
  }

  return {
    flex: width ? 0 : defaultFlex,
    width: width === 'auto' ? defaultFlex : getFirstDefined(width, minWidth, defaultFlex),
    maxWidth
  };
}

function getStylesForColumn(column, defaultFlex) {
  const { flex, width, maxWidth } = getSizesForColumn(column, defaultFlex);

  return {
    flex: `${flex} 0 auto`,
    width: `${width}px`,
    maxWidth: `${maxWidth}px`
  };
}

const propTypes = {
  defaultFlex: PropTypes.number
};

const useMain = props => {
  PropTypes.checkPropTypes(propTypes, props, 'property', 'useFlexLayout');

  const {
    defaultFlex = 1,
    columns,
    hooks: { getRowProps, getHeaderGroupProps, getHeaderProps, getCellProps }
  } = props;

  const visibleColumns = columns.filter(column => column.visible);

  let sumWidth = 0;
  visibleColumns.forEach(column => {
    const { width, minWidth } = getSizesForColumn(column, defaultFlex);
    if (width) {
      sumWidth += width;
    } else if (minWidth) {
      sumWidth += minWidth;
    } else {
      sumWidth += defaultFlex;
    }
  });

  const rowStyles = {
    style: {
      display: 'flex',
      minWidth: `${sumWidth}px`
    }
  };

  getRowProps.push(() => rowStyles);
  getHeaderGroupProps.push(() => rowStyles);

  getHeaderProps.push(column => ({
    style: {
      boxSizing: 'border-box',
      ...getStylesForColumn(column, defaultFlex)
    }
  }));

  getCellProps.push(cell => {
    return {
      style: {
        ...getStylesForColumn(cell.column, defaultFlex)
      }
    };
  });

  return props;
};

const useFlexLayout = hooks => {
  hooks.useMain.push(useMain);
};

export default useFlexLayout;

Edit: removed some useless function parameters and general cleanup - when I was updating this hook a couple of days ago I only tried to make it work to be honest so I didn’t read too much into the code.

Yes. That’s a good idea.