He escrito un código para representar 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>
  );
} 

¿Hay una mejor manera de lograr esto?

(Me gustaría insertar bucles for dentro del código de la plantilla, o algún enfoque similar).

81
fadedbee 3 sep. 2014 a las 18:07

5 respuestas

La mejor respuesta

Puedes poner expresiones dentro de llaves. Observe en el JavaScript compilado por qué un bucle for nunca sería posible dentro de la sintaxis JSX; JSX equivale a llamadas a funciones y argumentos de funciones azucaradas. Solo se permiten expresiones.

(Además: recuerde agregar atributos key a los componentes representados 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);
              })
            )
          );
        })
      )
    )
  );
} 
126
isherwood 8 oct. 2018 a las 16:25

En el espíritu de la programación funcional, hagamos que nuestros componentes sean un poco más fáciles de trabajar mediante el uso de 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 nuestra 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 curry, pero las personas tienden a evitar el curry.

2
Brigand 3 sep. 2014 a las 19:33

Shallow (a través de Array from():

<table>
    { Array.from({length:3}, (value, index) => <tr key={value.id} />) }
</table>

Otra forma sería a través de Array {{X0} }:

<table>
    { Array(3).fill(<tr />) }
</table>

Nodos Anidados:

 var table = (
      <table>
        { Array.from(Array(3)).map((tr, tr_i) => 
            <tr> 
              { Array.from(Array(4)).map((a, td_i, arr) => 
                  <td>{arr.length * tr_i + td_i + 1}</td>
               )}
            </tr>
        )}
      </table>
);

ReactDOM.render(table, document.querySelector('main'))
td{ border:1px solid silver; padding:1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<main></main>
12
vsync 5 jun. 2019 a las 17:36

Para ampliar la respuesta de Ross Allen, aquí hay una variante ligeramente 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 return o ;), lo que facilita su colocación.

13
Jonathan. 29 ago. 2017 a las 14:34

Esta es, en mi opinión, la forma más elegante de hacerlo (con ES6). Crea una instancia de tu matriz vacía con 7 índices y mapea en una línea:

Array.apply(null, Array(7)).map((i)=>
<Somecomponent/>
)

Felicitaciones a https://php.quicoto.com/create-loop-inside-react -jsx /

1
Chris 14 oct. 2017 a las 20:48