He escrito un código para renderizar elementos repetidos en ReactJS, pero odio lo feo que es.
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>
);
}
¿Existe una mejor manera de lograrlo?
(Me gustaría incrustar forbucles dentro del código de la plantilla o algún enfoque similar).
javascript
reactjs
fadedbee
fuente
fuente

Respuestas:
Puede poner expresiones entre llaves. Observe en el JavaScript compilado por qué un
forbucle nunca sería posible dentro de la sintaxis JSX; JSX equivale a llamadas a funciones y argumentos de función azucarados. Solo se permiten expresiones.(Además: recuerde agregar
keyatributos a los componentes renderizados dentro de los bucles).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); }) ) ); }) ) ) ); }fuente
foramap. Como no sé cuáles son los datos en cada una de las estructuras de datos, asumí que las filas son matrices y usé el índice de la iteración parakey. Cuando se agregan / eliminan datos de la matriz, eso provocará una nueva representación innecesaria. Debe cambiarkeya un valor que identifique de manera única los datos y que no dependa del orden y / o tamaño de la matriz.forbucles y similares, ni tiene una sintaxis de plantilla para bucles.forbucle nunca sería posible.Para ampliar la respuesta de Ross Allen, aquí hay una variante un poco más limpia que usa la sintaxis de flecha ES6.
{this.props.titles.map(title => <th key={title}>{title}</th> )}Tiene la ventaja de que la parte JSX está aislada (no
returno;), lo que facilita la colocación de un bucle a su alrededor.fuente
Dado
Array(3)que creará una matriz no iterable , debe rellenarse para permitir el uso delmapmétodo Array. Una forma de "convertir" es destruirlo dentro de Array-brackets, lo que "obliga" a que el Array se llene conundefinedvalores, al igual queArray(N).fill(undefined)<table> { [...Array(3)].map((_, index) => <tr key={index}/>) } </table>Otra forma sería a través de Array
fill():<table> { Array(3).fill(<tr/>) } </table>El problema con el ejemplo anterior es la falta de
keyapoyo, que es imprescindible .( No se recomienda usar un iterador
indexcomokey)Nodos anidados:
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>fuente
Array.from({length: 5}, (value, index) => <tr />)En el espíritu de la programación funcional, hagamos que nuestros componentes sean un poco más fáciles de trabajar utilizando abstracciones.
// converts components into mappable functions var mappable = function(component){ return function(x, i){ return component({key: i}, x); } } // maps on 2-dimensional arrays var map2d = function(m1, m2, xss){ return xss.map(function(xs, i, arr){ return m1(xs.map(m2), i, arr); }); } var td = mappable(React.DOM.td); var tr = mappable(React.DOM.tr); var th = mappable(React.DOM.th);Ahora podemos definir nuestro render de esta manera:
render: function(){ return ( <table> <thead>{this.props.titles.map(th)}</thead> <tbody>{map2d(tr, td, this.props.rows)}</tbody> </table> ); }jsbin
Una alternativa a nuestro map2d sería una función de mapa con curry, pero la gente tiende a evitar curry.
fuente
keyatributo. El uso del índice significa que agregar / eliminar elementos obligará a volver a renderizar los objetos que podrían no haber cambiado.Esta es, en mi opinión, la forma más elegante de hacerlo (con ES6). Cree una instancia de su matriz vacía con 7 índices y mapee en una línea:
Array.apply(null, Array(7)).map((i)=> <Somecomponent/> )felicitaciones a https://php.quicoto.com/create-loop-inside-react-jsx/
fuente
Array(...Array(10)).map((v, i) => <SomeComponent />)