user2773755
user2773755

Reputation: 117

Render layout with N fixed columns in react JS

I'm trying to render a table that contains a fixed number of columns. I set a width in css, and a fixed number of columns in js code. The the table should be rendered. The problems I'm dealing with are the following: - the code to render N fixed columns in a table is so ugly and I think that there should be a way to do it with clean code - I couldn't find a function that append a component to the child of an element dynamically.

_renderProducts(): ReactElement {
  var cols_no = 4;
  var cols = [];
  for (var col = row_index; col < 0 && col < this.state.products.length; col+=1) {
    cols.push(
      <LayoutColumn className={cx('XElement/column')} />
    );
  }
  for (var row_index = 0; row_index < this.state.products.length;row_index+=cols_no) {
    for (var col = 0; col < cols.length && col < this.state.products.length; col+=1) {
      cols[col].appendchild(  // THIS DOESN"T EXISTS
          <XCard
            product={this.state.products[col]} />
      )
    }
  }
  return (
    <Layout>
      {cols}
    </Layout>
);

}

I spent several hours trying to find a proper way to do this without success.

Upvotes: 0

Views: 2281

Answers (1)

Icepickle
Icepickle

Reputation: 12806

It is not a good idea to manipulate the dom inside react.

To map children, in general, you make sub components that each render a part of the application. Here the map function is used quite often to render the children of a current component.

You can find more examples here: https://facebook.github.io/react/docs/tutorial.html

I think you could change your logic in a similar way like this:

_renderProducts(): ReactElement {
    return <Layout>{ this.state.products.map(function(product, idx) {
        <LayoutColumn className={cx('XElement/column')} key={idx}>
            <XCard product={product} />
        </LayoutColumn>
    }) }</Layout>;
);

And if you want an example how you could split all elements and split components you could check this snippet

.col0, .col1, .col2, .col3, .col4, .col5 {
    width: 120px;
    text-align: left;
}
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.js"></script>
<script type='text/javascript' src="https://fb.me/react-with-addons-0.14.0.js"></script>
<script type='text/javascript' src="https://fb.me/react-dom-0.14.0.js"></script>
<script type="application/javascript;version=1.7" language="JavaScript 1.7">
  //<![CDATA[
var Header = React.createClass({
	propTypes: {
    	title: React.PropTypes.string,
        className: React.PropTypes.string
    },
    render: function() {
    	var { title, className } = this.props;
    	return <th className={className}>{title}</th>;
    }
});

var ElementRow = React.createClass({
	propTypes: {
    	values: React.PropTypes.arrayOf(React.PropTypes.any)
    },
    render: function() {
    	var { values } = this.props;
        if (!values) {
        	return null;
        }
        return <tr>{ values.map(function(i, k) {
        	return <Element className={'col' + i} value={i} key={k} />;
        }) }</tr>;
    }
});

var Element = React.createClass({
	propTypes: {
    	value: React.PropTypes.any,
        className: React.PropTypes.string
    },
    render: function() {
    	var { value, className } = this.props || '';
        return <td className={className}>{value}</td>
    }
});

var Example = React.createClass({
	propTypes: {
    	columns: React.PropTypes.array,
        rows: React.PropTypes.arrayOf(React.PropTypes.array)
    },
    renderHeaders: function(columns) {
        if (!columns) {
	        return null;
        }
        return columns.map(function(i, k) {
            return <Header title={i} key={k} className={'col' + k} />;
        });
    },
    renderBody: function(rows) {
    	if (!rows) {
        	return null;
        }
        return <tbody>{ rows.map(function(i, k) {
        		return <ElementRow values={i} key={k} />;
        	}) }</tbody>;
    },
    render: function() {
    	var { columns, rows } = this.props;
        if (!columns) {
        	return null;
        }
        return <table><thead>
        	<tr>{this.renderHeaders(columns)}</tr>
            </thead>
            {this.renderBody(rows)}
        </table>;
    }
});

var table = {
	columns: ['column1', 'column2', 'column3', 'column4', 'column5'],
    rows: [
    	['row1 - 1', 'row1 - 2', 'row1 - 3', 'row1 - 4', 'row1 - 5'],
    	['row2 - 1', 'row2 - 2', 'row2 - 3', 'row2 - 4', 'row2 - 5'],
    	['row3 - 1', 'row3 - 2', 'row3 - 3', 'row3 - 4', 'row3 - 5']
    ]
};
 
ReactDOM.render(
	<Example {...table} />,
    document.getElementById('container')
);

//]] >
</script>
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

Upvotes: 1

Related Questions