Ik'm probeer een jQuery component om te zetten naar React.js en een van de dingen waar ik'm moeite mee heb is het renderen van n aantal elementen op basis van een for loop.
Ik begrijp dat dit niet mogelijk is, of aanbevolen en dat waar een array bestaat in het model het volledig logisch is om map
te gebruiken. Dat is prima, maar hoe zit het als je geen array hebt? In plaats daarvan heb je een numerieke waarde die gelijk staat aan een bepaald aantal elementen om te renderen, wat moet je dan doen?
Hier's mijn voorbeeld, ik wil een element vooraf laten gaan door een willekeurig aantal span tags op basis van zijn hiërarchische niveau. Dus op niveau 3, wil ik 3 span tags voor het tekst element.
In javascript:
for (var i = 0; i < level; i++) {
$el.append('<span class="indent"></span>');
}
$el.append('Some text value');
Ik kan't schijnen om dit, of iets dergelijks te krijgen om te werken in een JSX React.js component. In plaats daarvan moest ik het volgende doen, eerst een temp array bouwen tot de juiste lengte en dan de array doorlussen.
React.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"
...
);
}
Dit kan toch's niet de beste, of enige manier zijn om dit te bereiken? Wat zie ik over het hoofd?
Bijgewerkt: Met ingang van React > 0.16
Render methode hoeft niet per se een enkel element te retourneren. Een array kan ook worden geretourneerd.
var indents = [];
for (var i = 0; i < this.props.level; i++) {
indents.push(<span className='indent' key={i}></span>);
}
return indents;
OF
return this.props.level.map((item, index) => (
<span className="indent" key={index}>
{index}
</span>
));
Docs hier met uitleg over JSX children
OLD:
Je kunt in plaats daarvan een lus gebruiken
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>
);
Je kunt ook .map en fancy es6
return (
<div>
{this.props.level.map((item, index) => (
<span className='indent' key={index} />
))}
"Some text value"
</div>
);
Ook moet je de return value in een container verpakken. Ik gebruikte div in het bovenstaande voorbeeld
Zoals de docs zeggen hier
Momenteel kun je in een component's render slechts één node retourneren; als je, zeg, een lijst van divs hebt om te retourneren, moet je je componenten wikkelen binnen een div, span of een andere component.
Hier is een functioneler voorbeeld met enkele ES6 functies:
'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;
Ik gebruik Object.keys(chars).map(...)
om te lussen in 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>
);
}