React-toolbox: Wrapped / composed TableRows do not get rendered by Table (v2)

Created on 12 Nov 2016  Â·  2Comments  Â·  Source: react-toolbox/react-toolbox

Hey, thanks for all your work on react-toolbox. We are trying out the css-next branch and really enjoying it. One issue that were having with the new table is wrapping TableRow in another component to be rendered in a table. E.g.

<Table selectable={false}>
  <TableHead>
    <TableCell>Widget</TableCell>
    <TableCell>Price</TableCell>
    <TableCell>Color</TableCell>
  </TableHead>
  { this.props.wigets.map((widget, i) => (
    <WidgetRow key={i} widget={widget} />
  ))}
</Table>

Where WidgetRow renders something like:

<TableRow>
  <TableCell>{this.props.widget.name}</TableCell>
  <TableCell>
    <Input
      type="text"
      value={this.state.price}
      onChange={this.handlePriceChange}
      onBlur={this.savePriceChange}
    />
  </TableCell>
  <TableCell>
    <Input
      type="text"
      value={this.state.color}
      onChange={this.handleColorChange}
      onBlur={this.saveColorChange}
    />
  </TableCell>
</TableRow>

We thought it would be good to extract table rows into their own component so that we wouldn't have to maintain a multi-dimensional array of states for each widget/attribute. Is this a use-case you would like to support for the new react-toolbox tables? Is there another prefered method to accomplish this? Would you be open to a pull request to allow for components to wrap TableRow in a Table?.

Most helpful comment

The most interesting way to solve this is by using dependency injection. If you look at the code here you will see there is a factory function exposed to build the Table component. This means you can manually invoke this factory injecting your custom component. For example:

// CustomTable.js
import { themr } from 'react-css-themr';
import { TABLE } from 'react-toolbox/lib/identifiers';
import { factory as tableFactory } from 'react-toolbox/lib/table/Table';
import { TableRow, TableHead } from 'react-toolbox/lib/table';

// Define your custom row
const CustomRow = props => <TableRow {...props} />;

// Create a new Table component injecting Head and Row
// Feel free to inject default styles there, check index.js
const Table = themr(TABLE)(tableFactory(TableHead, CustomRow));

export default Table;
export { TableHead };
export { CustomRow as TableRow };

Another (way more straightforward alternative) would be to add two properties to the Table component accepting TableHead and TableRow but I prefer this one because it clearly separates component dependencies from props.

All 2 comments

The most interesting way to solve this is by using dependency injection. If you look at the code here you will see there is a factory function exposed to build the Table component. This means you can manually invoke this factory injecting your custom component. For example:

// CustomTable.js
import { themr } from 'react-css-themr';
import { TABLE } from 'react-toolbox/lib/identifiers';
import { factory as tableFactory } from 'react-toolbox/lib/table/Table';
import { TableRow, TableHead } from 'react-toolbox/lib/table';

// Define your custom row
const CustomRow = props => <TableRow {...props} />;

// Create a new Table component injecting Head and Row
// Feel free to inject default styles there, check index.js
const Table = themr(TABLE)(tableFactory(TableHead, CustomRow));

export default Table;
export { TableHead };
export { CustomRow as TableRow };

Another (way more straightforward alternative) would be to add two properties to the Table component accepting TableHead and TableRow but I prefer this one because it clearly separates component dependencies from props.

I did this and still not rendering.

Doing some debug

function defaultChecker(classType, reactElement) {
  console.log(reactElement.type === classType);
  console.log(classType);
  console.log(reactElement.type);
  return reactElement && reactElement.type === classType;
}

My code

import React from 'react';

import { themr } from 'react-css-themr';
import { TABLE } from 'react-toolbox/lib/identifiers';
import { tableFactory } from 'react-toolbox/lib/table/Table';
import { TableHead, TableCell } from 'react-toolbox/lib/table';

import TableRow from './ListItem';


const Table = themr(TABLE)(tableFactory(TableHead, TableRow));


const CategoryList = ({ categories, onActiveStatusChanged }) => (
  <Table selectable={false} >
    <TableHead>
      <TableCell>Nombre</TableCell>
      <TableCell>Slug</TableCell>
      <TableCell>Está activo</TableCell>
    </TableHead>
    {categories.map(item => (
      <TableRow
        category={item}
        onActiveStatusChanged={onActiveStatusChanged}
        key={item._id}
      />
    ))}
  </Table>
);

CategoryList.propTypes = {
  categories: React.PropTypes.arrayOf(React.PropTypes.shape({
    name: React.PropTypes.string.isRequired,
    slug: React.PropTypes.string.isRequired,
    is_active: React.PropTypes.bool,
  })).isRequired,
  onActiveStatusChanged: React.PropTypes.func.isRequired,
};

CategoryList.defaultProps = {

};


export default CategoryList;

The console output is:

false
is-component-of-type.js:28 function ListItem() {
    var _ref;

    var _temp, _this, _ret;

    _classCallCheck(this, ListItem);

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
     …
is-component-of-type.js:29 function ListItem() {
    var _ref;

    var _temp, _this, _ret;

    _classCallCheck(this, ListItem);

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
     …
Was this page helpful?
0 / 5 - 0 ratings

Related issues

raka9256 picture raka9256  Â·  3Comments

wtgtybhertgeghgtwtg picture wtgtybhertgeghgtwtg  Â·  3Comments

guacamoli picture guacamoli  Â·  4Comments

landabaso picture landabaso  Â·  4Comments

saintc0d3r picture saintc0d3r  Â·  4Comments