I'm tentando converter um componente jQuery para React.js e uma das coisas que I'm tendo dificuldade com é renderizar n número de elementos baseados em um loop for.
Eu entendo que isso não é possível, ou recomendado, e que onde existe um array no modelo faz todo o sentido utilizar o `mapa'. Isso'está bem, mas e quando você não tem um array? Ao invés disso você tem um valor numérico que equivale a um dado número de elementos a renderizar, então o que você deve fazer?
Aqui's meu exemplo, eu quero prefixar um elemento com um número arbitrário de tags de span com base nele's nível hierárquico. Então no nível 3, eu quero 3 tags de span antes do elemento de texto.
Em javascript:
for (var i = 0; i < level; i++) {
$el.append('<span class="indent"></span>');
}
$el.append('Some text value');
Eu posso'não consigo perceber isto, ou algo semelhante ao trabalho numa componente do JSX React.js. Em vez disso eu tive que fazer o seguinte, primeiro construindo um array temporário com o comprimento correto e depois fazendo o looping do array.
Reagir.js
render: function() {
var tmp = [];
for (var i = 0; i < this.props.level; i++) {
tmp.push(i);
}
var indents = tmp.map(function (i) {
return (
<span className='indent'></span>
);
});
return (
...
{indents}
"Some text value"
...
);
}
Certamente esta pode'não é a melhor, ou a única maneira de conseguir isto? O que eu estou perdendo?
**Atualizado: A partir de React > 0,16***
O método de renderização não tem necessariamente que devolver um único elemento. Um array também pode ser retornado.
var indents = [];
for (var i = 0; i < this.props.level; i++) {
indents.push(<span className='indent' key={i}></span>);
}
return indents;
OU
return this.props.level.map((item, index) => (
<span className="indent" key={index}>
{index}
</span>
));
Docs aqui a explicar sobre as crianças JSX
OURO:
Você pode usar um laço em vez disso
var indents = [];
for (var i = 0; i < this.props.level; i++) {
indents.push(<span className='indent' key={i}></span>);
}
return (
<div>
{indents}
"Some text value"
</div>
);
Você também pode usar **.map*** e es6
return (
<div>
{this.props.level.map((item, index) => (
<span className='indent' key={index} />
))}
"Some text value"
</div>
);
Além disso, você tem que embrulhar o valor de retorno em um recipiente. Eu usei o div no exemplo acima
Como dizem os documentos aqui.
Atualmente, em um componente's render, você só pode retornar um nó; se você tiver, digamos, uma lista de divs a retornar, você deve embrulhar seus componentes dentro de um div, span ou qualquer outro componente.
Aqui está um exemplo mais funcional com algumas funcionalidades do ES6:
'use strict';
const React = require('react');
function renderArticles(articles) {
if (articles.length > 0) {
return articles.map((article, index) => (
<Article key={index} article={article} />
));
}
else return [];
}
const Article = ({article}) => {
return (
<article key={article.id}>
<a href={article.link}>{article.title}</a>
<p>{article.description}</p>
</article>
);
};
const Articles = React.createClass({
render() {
const articles = renderArticles(this.props.articles);
return (
<section>
{ articles }
</section>
);
}
});
module.exports = Articles;
I'm utilizando Object.keys(chars).map(...)
para fazer loop no render
// chars = {a:true, b:false, ..., z:false}
render() {
return (
<div>
{chars && Object.keys(chars).map(function(char, idx) {
return <span key={idx}>{char}</span>;
}.bind(this))}
"Some text value"
</div>
);
}