Estoy tratando de 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 se JSX
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).
Piense en ello como si estuviera llamando a funciones de JavaScript. No puede usar un for
bucle donde irían los argumentos de una llamada de función:
return tbody(
for (var i = 0; i < numrows; i++) {
ObjectRow()
}
)
Vea cómo tbody
se pasa un for
bucle a la función como argumento, lo que genera un error de sintaxis.
Pero puedes hacer una matriz y luego pasarla como argumento:
var rows = [];
for (var i = 0; i < numrows; i++) {
rows.push(ObjectRow());
}
return tbody(rows);
Básicamente, puede usar la misma estructura cuando trabaja con JSX:
var rows = [];
for (var i = 0; i < numrows; i++) {
// note: we are adding 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.
No estoy seguro de si esto funcionará para su situación, pero a menudo el mapa es una buena respuesta.
Si este era tu código con el bucle for:
<tbody>
for (var i=0; i < objects.length; i++) {
<ObjectRow obj={objects[i]} key={i}>
}
</tbody>
Podrías escribirlo así con el mapa :
<tbody>
{objects.map(function(object, i){
return <ObjectRow obj={object} key={i} />;
})}
</tbody>
Sintaxis de ES6:
<tbody>
{objects.map((object, i) => <ObjectRow obj={object} key={i} />)}
</tbody>
Si aún no tiene una matriz para map()
que le guste la respuesta de @ FakeRainBrigand, y desea alinear esto para que el diseño de la fuente corresponda a la salida más cercana que la respuesta de @ SophieAlpert:
http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=preview
<tbody>
{[...Array(10)].map((x, i) =>
<ObjectRow key={i} />
)}
</tbody>
Re: transpiling con Babel, su página de advertencias dice que Array.from
es necesario para la difusión, pero en la actualidad ( v5.8.23
) no parece ser el caso cuando se difunde un archivo Array
. Tengo un problema de documentación abierto para aclarar eso. Pero úselo bajo su propio riesgo o polyfill.
Array.apply
<tbody>
{Array.apply(0, Array(10)).map(function (x, i) {
return <ObjectRow key={i} />;
})}
</tbody>
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>
Mantenga el diseño de la 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>
);
}
Array
métodos de ES2015Con Array.prototype.fill
podría hacer esto como una alternativa al uso de spread como se ilustra arriba:
<tbody>
{Array(10).fill(1).map((el, i) =>
<ObjectRow key={i} />
)}
</tbody>
(Creo que en realidad podrías omitir cualquier argumento 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, el key
atributo alivia una advertencia con la compilación de desarrollo, pero no es accesible en el niño. Puede pasar un atributo adicional si desea que el índice esté disponible en el niño. Consulte Listas y claves para obtener más información.
Simplemente usando el método map Array con sintaxis ES6:
<tbody>
{items.map(item => <ObjectRow key={item.id} name={item.name} />)}
</tbody>
No olvide la key
propiedad.
El uso de la función Array map es una forma muy común de recorrer una matriz de elementos y crear componentes de acuerdo con ellos en React , esta es una excelente manera de hacer un bucle que es una forma bastante eficiente y ordenada de hacer sus bucles en JSX . no es la única forma de hacerlo, sino la forma preferida.
Además, no olvide tener una clave única para cada iteración según sea necesario. La función de mapa crea un índice único a partir de 0, pero no se recomienda usar el índice producido, pero si su valor es único o si hay una clave única, puede usarlos:
<tbody>
{numrows.map(x=> <ObjectRow key={x.id} />)}
</tbody>
Además, algunas líneas de MDN si no está familiarizado con la función de mapa en Array:
map invoca una función de devolución de llamada proporcionada una vez para cada elemento de una matriz, en orden, y construye una nueva matriz a partir de los resultados. La devolución de llamada se invoca solo para los índices de la matriz que tienen valores asignados, incluido el indefinido. No se llama por elementos faltantes de la matriz (es decir, índices que nunca se han establecido, que se han eliminado o 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 atraviesa.
Si se proporciona un parámetro thisArg al mapa, se utilizará como este valor de devolución de llamada. De lo contrario, el valor indefinido se utilizará como este valor. Este valor finalmente observable por la devolución de llamada se determina de acuerdo con las reglas habituales para determinar el esto visto por una función.
map no muta la matriz en la que se llama (aunque la devolución de llamada, si se invoca, puede hacerlo).
Si ya está utilizando lodash
, la _.times
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>
);
}
}
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>);
}
Sé que este es un hilo antiguo, pero es posible que desee verificar React Templates , que le permite usar plantillas de estilo jsx en React , con algunas directivas (como rt-repeat).
Su ejemplo, si usara react-templates, sería:
<tbody>
<ObjectRow rt-repeat="obj in objects"/>
</tbody>
Hay varias formas de hacerlo. JSX finalmente se compila en JavaScript, por lo que siempre que esté escribiendo JavaScript válido, estará bien.
Mi respuesta apunta a consolidar todas las maravillosas formas ya presentadas aquí:
Si no tiene una matriz de objeto, simplemente el número de filas:
dentro del return
bloque, creando Array
y usando Array.prototype.map
:
render() {
return (
<tbody>
{Array(numrows).fill(null).map((value, index) => (
<ObjectRow key={index}>
))}
</tbody>
);
}
fuera del return
bloque, simplemente use un bucle for JavaScript normal:
render() {
let rows = [];
for (let i = 0; i < numrows; i++) {
rows.push(<ObjectRow key={i}/>);
}
return (
<tbody>{rows}</tbody>
);
}
expresión de función inmediatamente invocada:
render() {
return (
<tbody>
{() => {
let rows = [];
for (let i = 0; i < numrows; i++) {
rows.push(<ObjectRow key={i}/>);
}
return rows;
}}
</tbody>
);
}
Si tienes una matriz de objetos
dentro del return
bloque, .map()
cada objeto a un <ObjectRow>
componente:
render() {
return (
<tbody>
{objectRows.map((row, index) => (
<ObjectRow key={index} data={row} />
))}
</tbody>
);
}
fuera del return
bloque, simplemente use un bucle for JavaScript normal:
render() {
let rows = [];
for (let i = 0; i < objectRows.length; i++) {
rows.push(<ObjectRow key={i} data={objectRows[i]} />);
}
return (
<tbody>{rows}</tbody>
);
}
expresión de función inmediatamente invocada:
render() {
return (
<tbody>
{(() => {
const rows = [];
for (let i = 0; i < objectRows.length; i++) {
rows.push(<ObjectRow key={i} data={objectRows[i]} />);
}
return rows;
})()}
</tbody>
);
}
si 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 admitir filtros, reducir, etc.
Hay varias respuestas que apuntan al uso de la map
declaración. Aquí está un ejemplo completo utilizando un repetidor dentro del listaCaracterísticas componente a la lista de funciones componentes basado en una estructura de datos llamada JSON características .
const FeatureList = ({ features, onClickFeature, onClickLikes }) => (
<div className="feature-list">
{features.map(feature =>
<Feature
key={feature.id}
{...feature}
onClickFeature={() => onClickFeature(feature.id)}
onClickLikes={() => onClickLikes(feature.id)}
/>
)}
</div>
);
Puede ver el código FeatureList completo en GitHub. El accesorio de características se enumera aquí .
Para realizar un bucle varias veces y regresar, puede lograrlo con la ayuda de from
y map
:
<tbody>
{
Array.from(Array(i)).map(() => <ObjectRow />)
}
</tbody>
dónde i = number of times
Si desea asignar ID de clave únicos a los componentes renderizados, puede usarlos React.Children.toArray
como se propone en la documentación de React
React.Children.toArray
Devuelve la estructura de datos opaca de los niños como una matriz plana con claves asignadas a cada niño. Útil si desea manipular colecciones de niños en sus métodos de renderizado, especialmente si desea reordenar o dividir this.props.children antes de pasarlo.
Nota:
React.Children.toArray()
cambia las claves para preservar la semántica de las matrices anidadas al aplanar listas de hijos. Es decir, toArray antepone cada clave en la matriz devuelta para que la clave de cada elemento tenga como alcance la matriz de entrada que la contiene.
<tbody>
{
React.Children.toArray(
Array.from(Array(i)).map(() => <ObjectRow />)
)
}
</tbody>
digamos que tenemos una variedad de elementos en su estado:
[{name: "item1", id: 1}, {name: "item2", id: 2}, {name: "item3", id: 3}]
<tbody>
{this.state.items.map((item) => {
<ObjectRow key={item.id} name={item.name} />
})}
</tbody>
Si opta por convertir este retorno interno () del método de representación , la opción más fácil sería usar el método map () . Asigne su matriz a la sintaxis JSX usando la función map (), como se muestra a continuación ( se usa la sintaxis ES6 ).
Dentro del componente principal :
<tbody>
{ objectArray.map(object => <ObjectRow key={object.id} object={object.value}>) }
</tbody>
Tenga en cuenta el key
atributo agregado a su componente secundario. Si no proporcionó un atributo clave, puede ver la siguiente advertencia en su consola.
Advertencia: cada niño en una matriz o iterador debe tener una propiedad de "clave" única.
Nota: Un error común que comete la gente es usar index
como clave al iterar, usar index
el elemento como clave es un anti-patrón y puede leer más sobre esto aquí . En resumen, si NO es una lista estática, nunca la use index
como clave.
Ahora, en el componente ObjectRow , puede acceder al objeto desde sus propiedades.
Dentro del componente ObjectRow
const { object } = this.props
o
const object = this.props.object
Esto debería traerle el objeto que pasó del componente principal a la variable object
en el componente ObjectRow . Ahora puede escupir los valores en ese objeto de acuerdo con su propósito.
Referencias:
Una posibilidad de ES2015 / Babel es usar una función de generador para crear una matriz de JSX:
function* jsxLoop(times, callback)
{
for(var i = 0; i < times; ++i)
yield callback(i);
}
...
<tbody>
{[...jsxLoop(numrows, i =>
<ObjectRow key={i}/>
)]}
</tbody>
Si no tiene nada .map()
que pueda usar Array.from()
con la map
función para repetir elementos:
<tbody>
{Array.from({ length: 5 }, (value, key) => <ObjectRow key={key} />)}
</tbody>
Yo uso esto:
gridItems = this.state.applications.map(app =>
<ApplicationItem key={app.Id} app={app } />
);
PD: ¡nunca olvides la clave o tendrás muchas advertencias!
... O también puede preparar una matriz de objetos y asignarla a una función para obtener la salida deseada. Prefiero esto, porque me ayuda a mantener la buena práctica de codificar sin lógica dentro del retorno de render.
render() {
const mapItem = [];
for(let i =0;i<item.length;i++)
mapItem.push(i);
const singleItem => (item, index) {
// item the single item in the array
// the index of the item in the array
// can implement any logic here
return (
<ObjectRow/>
)
}
return(
<tbody>{mapItem.map(singleItem)}</tbody>
)
}
Simplemente use .map()
para recorrer su colección y devolver <ObjectRow>
elementos con accesorios de cada iteración.
Suponiendo que objects
hay una matriz en alguna parte ...
<tbody>
{ objects.map((obj, index) => <ObjectRow obj={ obj } key={ index }/> ) }
</tbody>
Tiendo a favorecer un enfoque donde la lógica de programación ocurre fuera del valor de retorno de render
. Esto ayuda a que lo que se hace realmente fácil de asimilar.
Entonces probablemente haría algo como:
import _ from 'lodash';
...
const TableBody = ({ objects }) => {
const objectRows = objects.map(obj => <ObjectRow object={obj} />);
return <tbody>{objectRows}</tbody>;
}
Es cierto que esta es una cantidad tan pequeña de código que insertarlo podría funcionar bien.
por supuesto, puede resolver con un .map como lo sugiere la otra respuesta. Si ya usa babel, podría pensar en usar declaraciones de control jsx. Requieren un poco de configuración, pero creo que vale la pena en términos de legibilidad (especialmente para desarrolladores que no reaccionan). Si usa un linter, también hay declaraciones eslint-plugin-jsx-control-
Su código JSX se compilará en código JavaScript puro, cualquier etiqueta será reemplazada por ReactElement
objetos. En JavaScript, no puede llamar a una función varias veces para recopilar sus variables devueltas.
Es ilegal, la única forma es usar una matriz para almacenar las variables devueltas por la función.
O puede usar el Array.prototype.map
que está disponible desde JavaScript ES5 para manejar esta situación.
Tal vez podamos escribir otro compilador para recrear una nueva sintaxis JSX para implementar una función de repetición como la de Angularng-repeat
.
Esto se puede hacer de varias formas.
Como se sugirió anteriormente, antes de return
almacenar todos los elementos en la matriz
Bucle dentro return
Método 1
let container =[];
let arr = [1,2,3] //can be anything array, object
arr.forEach((val,index)=>{
container.push(<div key={index}>
val
</div>)
/**
* 1. All loop generated elements require a key
* 2. only one parent element can be placed in Array
* e.g. container.push(<div key={index}>
val
</div>
<div>
this will throw error
</div>
)
**/
});
return (
<div>
<div>any things goes here</div>
<div>{container}</div>
</div>
)
Método 2
return(
<div>
<div>any things goes here</div>
<div>
{(()=>{
let container =[];
let arr = [1,2,3] //can be anything array, object
arr.forEach((val,index)=>{
container.push(<div key={index}>
val
</div>)
});
return container;
})()}
</div>
</div>
)
Aquí tienes una solución sencilla.
var Object_rows = [];
for (var i = 0; i < numrows; i++) {
Object_rows.push(<ObjectRow />);
}
<tbody>{Object_rows}</tbody>;
No se requiere mapeo ni código complejo. Solo necesita empujar las filas a la matriz y devolver los valores para representarla.
Dado que está escribiendo sintaxis de Javascript dentro del código JSX, debe envolver su Javascript entre llaves.
row = () => {
var rows = [];
for (let i = 0; i<numrows; i++) {
rows.push(<ObjectRow/>);
}
return rows;
}
<tbody>
{this.row()}
</tbody>
También puede utilizar una función de autoinvocación:
return <tbody>
{(() => {
let row = []
for (var i = 0; i < numrows; i++) {
row.push(<ObjectRow key={i} />)
}
return row
})()}
</tbody>
Aquí hay una muestra del documento de React: Expresiones de JavaScript como hijos
function Item(props) {
return <li>{props.message}</li>;
}
function TodoList() {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
<ul>
{todos.map((message) => <Item key={message} message={message} />)}
</ul>
);
}
como tu caso, sugiero escribir así:
function render() {
return (
<tbody>
{numrows.map((roe, index) => <ObjectRow key={index} />)}
</tbody>
);
}
Tenga en cuenta que la clave es muy importante, porque React usa la clave para diferenciar los datos en la matriz.
Lo uso como
<tbody>
{ numrows ? (
numrows.map(obj => { return <ObjectRow /> })
) : null
}
</tbody>
Puedes hacer algo como:
let foo = [1,undefined,3]
{ foo.map(e => !!e ? <Object /> : null )}
Gran pregunta.
Lo que hago cuando quiero agregar una cierta cantidad de componentes es usar una función auxiliar.
Defina una función que devuelva JSX:
const myExample = () => {
let myArray = []
for(let i = 0; i<5;i++) {
myArray.push(<MyComponent/>)
}
return myArray
}
//... in JSX
<tbody>
{myExample()}
</tbody>
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Si este tráiler de pesadilla de la temporada más reciente de Great British Bake Off te asustó y te hizo no volver a ver el programa, es posible que tengas suerte: PBS no ha decidido si se transmitirá o no la última temporada en los Estados Unidos. actualización, para aquellos que no siguen sin aliento este tipo de drama de nicho: el presentador Paul Hollywood y la hermosa carpa llena de batidoras de colores pastel y cuadros se trasladaron de la BBC al Canal 4; Mary Berry, Sue Perkins y Mel Giedroyc renunciaron.
Foto: Netflix Oh, Hello On Broadway (Netflix): Después de llegar a Broadway el año pasado, los dos locos del Upper West Side interpretados por John Mulaney y Nick Kroll finalmente llegaron a Netflix. El especial consta del espectáculo en el escenario, algunos momentos entre bastidores y un invitado muy especial de “Too Much Tuna”.
¿Quiere probar un cepillo de dientes Sonicare sin gastar mucho dinero en uno de sus modelos favoritos de gama alta? Puede comprar un kit de la Serie 2 o Serie 3 por tan solo $ 30 hoy en Amazon. Haga clic aquí para ver la lista completa de modelos elegibles y tenga en cuenta que se descontarán $ 10 adicionales en su carrito.
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.