如何在React中循环一个对象?

118

我刚开始学习React,想循环遍历对象属性,但React提示对象不能作为有效的React子元素,有人能给我一些解决问题的建议吗?我已经添加了createFragment,但不确定应该放在哪里或者该采取什么方法?

JS

var tifs = {1: 'Joe', 2: 'Jane'};
var tifOptions = Object.keys(tifs).forEach(function(key) {
    return <option value={key}>{tifs[key]}</option>
});

渲染函数

render() {
        const model = this.props.model;

        let tifOptions = {};

        if(model.get('tifs')) {
            tifOptions = Object.keys(this.props.model.get('tifs')).forEach(function(key) {
                return <option value={key}>{this.props.model.get('tifs')[key]}</option>
            });
        }

        return (
            <div class={cellClasses}>

                    <div class="grid__col-5 text--center grid__col--bleed">
                        <h5 class="flush text--uppercase">TIF</h5>
                        <select id="tif" name="tif" onChange={this.handleChange}>
                            {tifOptions}
                        </select>
                    </div>

            </div>
        );
    }

控制台错误

If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object)

1
我之前遇到过类似的错误。奇怪的是,使用.map()方法解决了我的问题。这也很有趣:https://dev59.com/fVoT5IYBdhLWcg3w8jBm - justDan
8个回答

236
问题在于你使用了forEach()方法,它总会返回undefined。你可能正在寻找的是map()方法,它会返回一个新的数组:

问题在于你使用了forEach()方法,它总会返回undefined。你可能正在寻找的是map()方法,它会返回一个新的数组:

var tifOptions = Object.keys(tifs).map(function(key) {
    return <option value={key}>{tifs[key]}</option>
});

如果您仍然想使用forEach(),则需要像这样做:

var tifOptions = [];

Object.keys(tifs).forEach(function(key) {
    tifOptions.push(<option value={key}>{tifs[key]}</option>);
});

更新:

如果您正在编写ES6,您可以使用箭头函数以更简洁的方式实现同样的功能:

const tifOptions = Object.keys(tifs).map(key => 
    <option value={key}>{tifs[key]}</option>
)

这里有一个演示所有上述选项的 jsfiddle: https://jsfiddle.net/fs7sagep/


38
您可以更加简洁地使用它,例如:
const tifs = {1: 'Joe', 2: 'Jane'};
...

return (
   <select id="tif" name="tif" onChange={this.handleChange}>  
      { Object.entries(tifs).map((t,k) => <option key={k} value={t[0]}>{t[1]}</option>) }          
   </select>
)

还有另一种略微不同的风味:

 Object.entries(tifs).map(([key,value],i) => <option key={i} value={key}>{value}</option>)  

15

当我使用Object.entriesmap时,我会像以下这样使用数组解构,然后直接调用它们。

Object.entries(tifs).map(([key, value]) => (
    <div key={key}>{value}</div>
));

7
const tifOptions = [];

for (const [key, value] of Object.entries(tifs)) {
    tifOptions.push(<option value={key} key={key}>{value}</option>);
}

return (
   <select id="tif" name="tif" onChange={this.handleChange}>  
      { tifOptions }          
   </select>
)

最终我不得不使用.entries而不是.map来避免React报错:Element implicitly has an 'any' type because index expression is not of type 'number' - slim

5
你也可以只使用以下的返回div,并利用Javascript内置的模板字面量:
```html

你也可以只有一个返回div,然后使用JavaScript内置的模板字符串字面量,如下所示:

```
const tifs = {1: 'Joe', 2: 'Jane'};

return(

        <div>
            {Object.keys(tifOptions).map((key)=>(
                <p>{paragraphs[`${key}`]}</p>
            ))}
        </div>
    )

4
您可以使用map函数。
{Object.keys(tifs).map(key => (
    <option value={key}>{tifs[key]}</option>
))}

2
{
   Object.entries(tifOptions).map(([key, value], index) =>
       console.log("Key" + Key + "::>" + "Value" + value);
)}

2
考虑到问题的年龄和其他得到赞同的答案,这种仅包含代码的回答并不是很有用。如果您有更现代的解决方案,请在帖子中添加评论,解释为什么这是2022年更好的方法。链接到文档、基准测试等。将此代码粘贴到此处并没有帮助任何人。原始问题已经被解决,而在2022年找到这篇文章的人不需要确切的解决方案,而是需要理解。 - Chris Baker

-9
我强烈建议您在进行React迭代时使用数组而不是对象,这是我经常使用的语法。
const rooms = this.state.array.map((e, i) =>(<div key={i}>{e}</div>))

要使用该元素,只需在您的jsx中放置{rooms}

其中e=数组的元素,i=元素的索引。在这里阅读更多信息。 如果您正在寻找迭代,这就是实现它的方法。


1
当使用对象时,键通常是ID而不是索引。然而,如果所有的键都是索引,我同意你的观点。 - tobiasandersen
谢谢您的评论,但我并不是在讨论对象。使用数组对我来说似乎是最好的选择,而且文档也提供了很好的支持。键值完全不是必要的,它们只是为了保持元素的顺序。索引方法并不是由我发明的,这是写在文档中的 :P - alex1997
1
数组并不总是最佳选择,尽管它们经常被使用。例如在缓存时,我通常会采用 Map 或对象。而且,在 React 中虽然会根据索引添加键,但当你没有显式提供它们时,确实存在使用场景。 - tobiasandersen
这完全没有回答问题。 - reggaeguitar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接