I've written some code to render repeating elements in ReactJS, but I hate how ugly it is.
render: function(){ var titles = this.props.titles.map(function(title) { return <th>{title}</th>; }); var rows = this.props.rows.map(function(row) { var cells = []; for (var i in row) { cells.push(<td>{row[i]}</td>); } return <tr>{cells}</tr>; }); return ( <table className="MyClassName"> <thead> <tr>{titles}</tr> </thead> <tbody>{rows}</tbody> </table> ); }
Is there a better way to achieve this?
(I would like to embed for
loops within the template code, or some similar approach.)
render() should return single element. You can split it up and have multiple components which implement some dedicated logic which is better and used to be a good practice in React.
In the ReactDOM. render you still can't render multiple items because react needs a root. So you can render a single component inside the ReactDOM. render and render an array of items in the internal component.
You can put expressions inside braces. Notice in the compiled JavaScript why a for
loop would never be possible inside JSX syntax; JSX amounts to function calls and sugared function arguments. Only expressions are allowed.
(Also: Remember to add key
attributes to components rendered inside loops.)
JSX + ES2015:
render() { return ( <table className="MyClassName"> <thead> <tr> {this.props.titles.map(title => <th key={title}>{title}</th> )} </tr> </thead> <tbody> {this.props.rows.map((row, i) => <tr key={i}> {row.map((col, j) => <td key={j}>{col}</td> )} </tr> )} </tbody> </table> ); }
JavaScript:
render: function() { return ( React.DOM.table({className: "MyClassName"}, React.DOM.thead(null, React.DOM.tr(null, this.props.titles.map(function(title) { return React.DOM.th({key: title}, title); }) ) ), React.DOM.tbody(null, this.props.rows.map(function(row, i) { return ( React.DOM.tr({key: i}, row.map(function(col, j) { return React.DOM.td({key: j}, col); }) ) ); }) ) ) ); }
Since Array(3)
will create an un-iterable array, it must be populated to allow the usage of the map
Array method. A way to "convert" is to destruct it inside Array-brackets, which "forces" the Array to be filled with undefined
values, same as Array(N).fill(undefined)
<table> { [...Array(3)].map((_, index) => <tr key={index}/>) } </table>
fill()
:<table> { Array(3).fill(<tr/>) } </table>
⚠️ Problem with above example is the lack of
key
prop, which is a must.
(Using an iterator'sindex
askey
is not recommended)
const tableSize = [3,4] const Table = ( <table> <tbody> { [...Array(tableSize[0])].map((tr, trIdx) => <tr key={trIdx}> { [...Array(tableSize[1])].map((a, tdIdx, arr) => <td key={trIdx + tdIdx}> {arr.length * trIdx + tdIdx + 1} </td> )} </tr> )} </tbody> </table> ); ReactDOM.render(Table, document.querySelector('main'))
td{ border:1px solid silver; padding:1em; }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <main></main>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With