如何在没有要映射的对象数组的情况下循环和渲染React.js中的元素?


145

我正在尝试将jQuery组件转换为React.js,而我遇到的困难之一是基于for循环渲染n个元素。

我了解这是不可能的,也不建议这样做,并且在模型中存在数组的地方使用它完全有意义map。很好,但是当您没有数组时该怎么办?取而代之的是,您拥有一个等于要渲染的给定元素数量的数值,那么您应该怎么做?

这是我的示例,我想根据元素的层次结构级别为元素添加任意数量的span标签。因此,在第3级,我要在text元素之前添加3个span标签。

在javascript中:

for (var i = 0; i < level; i++) {
    $el.append('<span class="indent"></span>');
}
$el.append('Some text value');

我似乎无法得到这个,或者与JSX React.js组件中的工作类似的东西。相反,我必须执行以下操作,首先将临时数组构建为正确的长度,然后循环该数组。

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"
    ...
  );
}

当然,这不是最好的方法还是唯一的方法?我想念什么?



您也可以这样做:jsfiddle.net/crl/69z2wepo/19804
caub 2015年

Answers:


241

更新:从React> 0.16开始

渲染方法不一定必须返回单个元素。也可以返回一个数组。

var indents = [];
for (var i = 0; i < this.props.level; i++) {
  indents.push(<span className='indent' key={i}></span>);
}
return indents;

要么

return this.props.level.map((item, index) => (
    <span className="indent" key={index}>
        {index}
    </span>
));

此处的文档介绍了有关JSX子级的信息


旧:

您可以改用一个循环

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>
);

您还可以使用.map和fancy es6

return (
   <div>
    {this.props.level.map((item, index) => (
       <span className='indent' key={index} />
    ))}
    "Some text value"
   </div>
);

同样,您必须将返回值包装在容器中。我在上面的示例中使用了div

正如文档在这里说的

当前,在组件的渲染中,您只能返回一个节点。如果您有要返回的div列表,则必须将组件包装在div,span或任何其他组件中。


1
那行得通,而且要简单得多。是的,我知道您必须将返回值包装在容器中,我已经在执行此操作了,因为它只是示例中所缺少的。
Jonathan Miles

2
在循环内添加键。键在反应中很重要。
Aamir Afridi

4
我一直在找你我生活的全部
2009东海生日贺

2
@ElgsQianChen它不可能。它必须包裹一些标签。如果{缩进}返回单个DOM元素与它里面的内容,则其确定
DHIRAJ

2
我不明白为什么在此答案中提到map方法,因为它仅适用于Array对象,但问题明确指出并非如此。
flukyspore

47

这是具有某些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;

1
这看起来是最“反应”的方式。将值作为prop传递给另一个子组件。谢谢!
Michael Giovanni Pumo

太好了!当您的render()为html重磅时非常理想。
马修

为了使它更ES6你可以使用import React from "react"export default Articles
jonlink

1
这个答案甚至都没有尝试回答这个问题。问题很明确,即如何将a转换为for loop可映射的数组(或对象),以便在React组件中呈现n个项目而没有项目数组。您的解决方案完全忽略了这一事实,并假定从道具传递了一系列文章。
乔纳森·迈尔斯

17

我正在Object.keys(chars).map(...)循环渲染

// 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>
    );
}

您的答案对我有用,但仅在我添加之后chars && ...以及.bind(this)功能结束时才有效。我很好奇为什么只是Object...(依此类推)不起作用。我一直不确定。
m00saca '17

2
这没有回答问题,它专门说没有要解析的对象数组,并且解释明确说我想将for循环转换为映射以在React组件中进行渲染。您将数组替换为无助于回答问题的对象,或添加了任何其他值。
乔纳森·迈尔斯

16

Array.from()接受一个可迭代的对象以转换为数组和可选的map函数。您可以使用以下.length属性创建一个对象:

return Array.from({length: this.props.level}, (item, index) => 
  <span className="indent" key={index}></span>
);

上周听完这封信后,我碰巧看到了您的问题,因此这是应用我所学知识的最快方法!语法.fm
show /

1
正是我呈现X元素所需的内容,谢谢!
Liran H '18

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.