Pregunta Loop inside React JSX


Intento hacer algo como lo siguiente en React JSX (donde ObjectRow es un componente separado):

<tbody>
    for (var i=0; i < numrows; i++) {
        <ObjectRow/>
    } 
</tbody>

Me doy cuenta y entiendo por qué esto no es válido JSX, ya que JSX se asigna a llamadas de función. Sin embargo, viniendo de la tierra de la plantilla y siendo nuevo en JSX, no estoy seguro de cómo lograría lo anterior (agregando un componente varias veces).


736
2018-04-05 05:29


origen


Respuestas:


Piense que solo llama funciones de JavaScript. No puedes poner un for bucle dentro de una llamada de función:

return tbody(
    for (var i = 0; i < numrows; i++) {
        ObjectRow()
    } 
)

Pero puedes hacer una matriz y luego pasar eso:

var rows = [];
for (var i = 0; i < numrows; i++) {
    rows.push(ObjectRow());
}
return tbody(rows);

Puedes usar básicamente la misma estructura cuando trabajas con JSX:

var rows = [];
for (var i = 0; i < numrows; i++) {
    // note: we add a key prop here to allow react to uniquely identify each
    // element in this array. see: https://reactjs.org/docs/lists-and-keys.html
    rows.push(<ObjectRow key={i} />);
}
return <tbody>{rows}</tbody>;

Por cierto, mi ejemplo de JavaScript es casi exactamente en lo que se transforma ese ejemplo de JSX. Juega con Babel REPL para tener una idea de cómo funciona JSX.


754
2018-04-05 05:39



No estoy seguro si esto funcionará para su situación, pero a menudo mapa es una buena respuesta.

Si este era tu código con el ciclo for:

<tbody>
    for (var i=0; i < objects.length; i++) {
        <ObjectRow obj={objects[i]} key={i}>
    } 
</tbody>

Podrías escribirlo así con mapa:

<tbody>
    {objects.map(function(object, i){
        return <ObjectRow obj={object} key={i} />;
    })}
</tbody>

Sintaxis ES6:

<tbody>
    {objects.map((object, i) => <ObjectRow obj={object} key={i} />)}
</tbody>

639
2018-04-05 05:46



Si aún no tiene una matriz para map() como la respuesta de @FakeRainBrigand, y desea alinear esto para que el diseño de la fuente corresponda a la salida más cercana que @ SophieAlpert's answer:

Con sintaxis ES2015 (ES6) (funciones de extensión y flecha)

http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=preview

<tbody>
  {[...Array(10)].map((x, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

Re: transpiling con Babel, es Página de advertencias dice que Array.from es necesario para la propagación, pero en la actualidad (v5.8.23) que no parece ser el caso cuando se disemina un Array. tengo un problema de documentación abierto para aclarar eso. Pero utilícelo bajo su propio riesgo o polyfill.

Vainilla ES5

Array.apply

<tbody>
  {Array.apply(0, Array(10)).map(function (x, i) {
    return <ObjectRow key={i} />;
  })}
</tbody>

Inline IIFE

http://plnkr.co/edit/4kQjdTzd4w69g8Suu2hT?p=preview

<tbody>
  {(function (rows, i, len) {
    while (++i <= len) {
      rows.push(<ObjectRow key={i} />)
    }
    return rows;
  })([], 0, 10)}
</tbody>

Combinación de técnicas de otras respuestas

Mantenga el diseño de fuente correspondiente a la salida, pero haga que la parte en línea sea más compacta:

render: function () {
  var rows = [], i = 0, len = 10;
  while (++i <= len) rows.push(i);

  return (
    <tbody>
      {rows.map(function (i) {
        return <ObjectRow key={i} index={i} />;
      })}
    </tbody>
  );
}

Con la sintaxis ES2015 y Array métodos

Con Array.prototype.fill usted podría hacer esto como una alternativa al uso de propagación como se ilustra arriba:

<tbody>
  {Array(10).fill(1).map((el, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

(Creo que podrías omitir cualquier argumento para fill(), pero no estoy al 100% en eso.) Gracias a @FakeRainBrigand por corregir mi error en una versión anterior de la fill() solución (ver revisiones).

key

En todos los casos, key attr alivia una advertencia con la construcción de desarrollo, pero no es accesible en el niño. Puede pasar un attr extra si desea que el índice esté disponible en el niño. Ver Listas y Llaves Para discusión.


317
2018-04-14 14:08



Simplemente usando mapa  Formación método con sintaxis ES6:

<tbody>
  {items.map(item => <ObjectRow key={item.id} name={item.name} />)} 
</tbody>

No olvides key propiedad.


52
2017-10-30 04:35



Utilizando Mapa de matriz función es una forma muy común de recorrer un Formación de elementos y crear componentes de acuerdo a ellos en Reaccionar, esta es una gran manera de hacer un ciclo que es bastante eficiente y ordenado para hacer tus loops en JSX, Es no la única manera de hacerlo, pero el forma preferida 

Además, no olvides tener un llave unica para cada iteración según sea necesario. La función de mapa crea un índice único desde 0 pero no se recomienda usar el índice, pero si su valor es único o si hay una clave única, puede usarlos:

<tbody>
  {numrows.map(x=> <ObjectRow key={x.id} />)}
</tbody>

También pocas líneas de MDN si no está familiarizado con la función de mapa en Array:

mapa llama una función de devolución de llamada proporcionada una vez para cada elemento en un   array, en orden, y construye una nueva matriz a partir de los resultados. llamar de vuelta   se invoca solo para los índices de la matriz que tienen valores asignados,   incluyendo indefinido. No se pide que falten elementos del   matriz (es decir, índices que nunca se han establecido, que han sido   eliminado o a los que nunca se les ha asignado un valor).

la devolución de llamada se invoca con tres argumentos: el valor del elemento,   el índice del elemento y el objeto Array que se está atravesando.

Si se proporciona un parámetro thisArg al mapa, se usará como   la devolución de llamada tiene este valor. De lo contrario, el valor indefinido se utilizará como   es este valor Este valor finalmente observable por la devolución de llamada es   determinado de acuerdo con las reglas habituales para determinar esto visto   por una función.

el mapa no muta la matriz a la que se llama (aunque   la devolución de llamada, si se invoca, puede hacerlo).


41
2018-05-16 13:37



Si ya estás usando lodash, el _.times la función es útil.

import React, { Component } from 'react';
import Select from './Select';
import _ from 'lodash';

export default class App extends Component {
    render() {
        return (
            <div className="container">
                <ol>
                    {_.times(3, i =>
                        <li key={i}>
                            <Select onSelect={this.onSelect}>
                                <option value="1">bacon</option>
                                <option value="2">cheez</option>
                            </Select>
                        </li>
                    )}
                </ol>
            </div>
        );
    }
}

33
2017-10-05 05:35



También puede extraer fuera del bloque de retorno:

render: function() {
    var rows = [];
    for (var i = 0; i < numrows; i++) {
        rows.push(<ObjectRow key={i}/>);
    } 

    return (<tbody>{rows}</tbody>);
}

25
2018-01-04 05:53



Sé que este es un hilo antiguo, pero es posible que desee realizar el pago http://wix.github.io/react-templates/, que le permite usar plantillas de estilo jsx en reaccionar, con algunas directivas (como rt-repeat).

Su ejemplo, si utilizó reaccionar-plantillas, sería:

<tbody>
     <ObjectRow rt-repeat="obj in objects"/>
</tbody>

20
2018-02-02 19:35



if numrows es una matriz, y es muy simple.

<tbody>
   {numrows.map(item => <ObjectRow />)}
</tbody>

El tipo de datos de matriz en React es mucho mejor, la matriz puede respaldar una nueva matriz, y admite el filtro, reduce etc.


15
2018-01-11 09:49