Two things jump out at me when I look at your code.
The first is that you are returning an array of React components from the renderTemplates function. This may be okay depending on how you use the output. The key to remember is that the return value from your component's render function must be a single React component (e.g., if you wrap this result in another JSX tag, you're okay.)
Secondly, it appears that you are not letting data flow from the top-level component on down; specifically, that you do not use the Row component to pass data to Column components. This is what makes writing your loop so difficult. Instead of trying to manage both Rows and Columns, you need only to pass the data needed for a single row to a Row component. The Row component will then pass each piece of data to a Column component. This removes the need to juggle opening and closing tags and simplifies the code overall.
Following is an example implementation of what I have described. I use table-related tags for rendering, but you can use divs or whatever is most appropriate for you. At the time of writing, there isn't much information about what is in templates, so I've created a silly little example to use.
var KvpColumn = React.createClass({
render: function() {
return <td>{this.props.kvp.key}: {this.props.kvp.value}</td>;
}
});
var KvpRow = React.createClass({
render: function() {
return (
<tr>
{this.props.items.map(function(item) {
return <KvpColumn key={item.key} kvp={item}/>;
})}
</tr>
);
}
});
var ObjectIDsTable = React.createClass({
render: function() {
var templates = this.props.templates;
var propertyNames = Object.getOwnPropertyNames(templates);
var group = [];
var rows = [];
var cols = Number(this.props.cols) || 2;
for(var i = 0; i < propertyNames.length; i++) {
var key = propertyNames[i];
group.push({key: key, value: templates[key]});
if(group.length === cols) {
rows.push(<KvpRow key={group[0].key} items={group}/>);
group = [];
}
}
if(group.length > 0) { // catch any leftovers
rows.push(<KvpRow key={group[0].key} items={group}/>);
}
return <table>{rows}</table>;
}
});
// something silly as a simple example
var templates = { a: 'b', c: 'd', e: 'f', g: 'h', i: 'j' };
React.render(<ObjectIDsTable templates={templates} cols="2"/>, document.getElementById('app'));
If you have access to Underscore or lodash, you can simplify the logic in ObjectIDsTable a bit further (and avoid writing loops altogether!):
var ObjectIDsTable = React.createClass({
render: function() {
var templates = this.props.templates;
var rows = _.chain(Object.getOwnPropertyNames(templates))
.map(function(key) { return { key: key, value: templates[key] }; })
.chunk(this.props.cols || 2)
.map(function(group) { return <KvpRow key={group[0].key} items={group}/>; })
.value();
return <table>{rows}</table>;
}
});
You can see this in action on Plunker.
templatesvalue and the corresponding value expected forhtml?