如何在React中呈现一个对象数组?

105

请问如何在React.js中渲染列表?我是这样做的

https://plnkr.co/edit/X9Ov5roJtTSk9YhqYUdp?p=preview

class First extends React.Component {
  constructor (props){
    super(props);

  }

  render() {
     const data =[{"name":"test1"},{"name":"test2"}];
    const listItems = data.map((d) => <li key={d.name}>{d.name}</li>;
    
    return (
      <div>
      hello
      </div>
    );
  }
} 

嗨,我谷歌搜索并找到了许多类似于这篇文章的文章:http://jasonjl.me/blog/2015/04/18/rendering-list-of-elements-in-react-with-jsx/。 - user2024778
1
嗯...你分享的Plnkr应用对我来说无法正常运行。 - RayLoveless
6个回答

185

你可以用两种方法来实现:

第一种:

render() {
    const data =[{"name":"test1"},{"name":"test2"}];
    const listItems = data.map((d) => <li key={d.name}>{d.name}</li>);

    return (
      <div>
      {listItems }
      </div>
    );
  }

第二点:在返回语句中直接编写map函数

render() {
    const data =[{"name":"test1"},{"name":"test2"}];
    return (
      <div>
      {data.map(function(d, idx){
         return (<li key={idx}>{d.name}</li>)
       })}
      </div>
    );
  }

请分享Plunker。 - user944513
1
是的,正在处理中。您在plunker中没有包含babel。 - Shubham Khatri
请告诉我如何在 Plunker 中包含 Babel。 - user944513
5
为避免问题,请勿将循环的索引(idx)用作JSX元素的键属性。请阅读此文档:https://reactjs.org/docs/lists-and-keys.html#keys。相反,可以使用某个"d.id"而不是idx。 - Enrique René
正如Enrique René所提到的,应该避免使用数组索引,但是由于数据已经是对象数组,并且假设键是唯一的(例如name1,name2等),因此在第一个示例中使用它们是很好的选择。 - Carmine Tambascia
显示剩余3条评论

21

https://facebook.github.io/react/docs/jsx-in-depth.html#javascript-expressions

You can pass any JavaScript expression as children, by enclosing it within {}. For example, these expressions are equivalent:

<MyComponent>foo</MyComponent>

<MyComponent>{'foo'}</MyComponent>

This is often useful for rendering a list of JSX expressions of arbitrary length. For example, this renders an HTML list:

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

class First extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [{name: 'bob'}, {name: 'chris'}],
    };
  }
  
  render() {
    return (
      <ul>
        {this.state.data.map(d => <li key={d.name}>{d.name}</li>)}
      </ul>
    );
  }
}

ReactDOM.render(
  <First />,
  document.getElementById('root')
);
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>


8
Shubham的回答已经解释得非常好了。此回答是为了避免一些陷阱和重构成更易读的语法而补充的。
陷阱:在渲染对象数组时存在一个常见的误解,特别是在对数据执行更新或删除操作时。使用案例可能是从表行中删除项目。有时候预期被删除的行并没有被删除,而是其他行被删除了。
为了避免这种情况,在JSX树的循环根元素中使用key属性。此外,添加React的Fragment将避免在通过调用方法呈现时在ul和li之间添加另一个元素。
state = {
    userData: [
        { id: '1', name: 'Joe', user_type: 'Developer' },
        { id: '2', name: 'Hill', user_type: 'Designer' }
    ]
};

deleteUser = id => {
    // delete operation to remove item
};

renderItems = () => {
    const data = this.state.userData;

    const mapRows = data.map((item, index) => (
        <Fragment key={item.id}>
            <li>
                {/* Passing unique value to 'key' prop, eases process for virtual DOM to remove specific element and update HTML tree  */}
                <span>Name : {item.name}</span>
                <span>User Type: {item.user_type}</span>
                <button onClick={() => this.deleteUser(item.id)}>
                    Delete User
                </button>
            </li>
        </Fragment>
    ));
    return mapRows;
};

render() {
    return <ul>{this.renderItems()}</ul>;
}

重要提示:我们决定传递给key属性的值也很重要,常见的方法是使用.map()提供的index参数。

简而言之,但这种方法有一个缺点,尽可能避免使用它,并使用正在迭代的数据中的任何唯一id,例如item.id。有一篇很好的文章介绍了这个问题-https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318


为什么不直接将键放在<li>元素中,而不是包装在<fragment>中? - David Talbot
你也可以这样做。我添加了Fragment,因为它就像我的实践一样,Fragment非常好地合并DOM元素,确保在通过映射数据进行渲染时不会放置其他元素。 - Meet Zaveri

3

在app.js文件中尝试下面的代码,易于理解

function List({}) {
  var nameList = [
    { id: "01", firstname: "Rahul", lastname: "Gulati" },
    { id: "02", firstname: "Ronak", lastname: "Gupta" },
    { id: "03", firstname: "Vaishali", lastname: "Kohli" },
    { id: "04", firstname: "Peter", lastname: "Sharma" }
  ];
  const itemList = nameList.map((item) => (
    <li>
      {item.firstname} {item.lastname}
    </li>
  ));
  return (
    <div>
      <ol style={{ listStyleType: "none" }}>{itemList}</ol>
    </div>
  );
}

export default function App() {
  return (
    <div className="App">
      <List />
    </div>
  );
}

2
import React from 'react';

class RentalHome extends React.Component{
    constructor(){
        super();
        this.state = {
            rentals:[{
                _id: 1,
                title: "Nice Shahghouse Biryani",
                city: "Hyderabad",
                category: "condo",
                image: "http://via.placeholder.com/350x250",
                numOfRooms: 4,
                shared: true,
                description: "Very nice apartment in center of the city.",
                dailyPrice: 43
              },
              {
                _id: 2,
                title: "Modern apartment in center",
                city: "Bangalore",
                category: "apartment",
                image: "http://via.placeholder.com/350x250",
                numOfRooms: 1,
                shared: false,
                description: "Very nice apartment in center of the city.",
                dailyPrice: 11
              },
              {
                _id: 3,
                title: "Old house in nature",
                city: "Patna",
                category: "house",
                image: "http://via.placeholder.com/350x250",
                numOfRooms: 5,
                shared: true,
                description: "Very nice apartment in center of the city.",
                dailyPrice: 23
              }]
        }
    }
    render(){
        const {rentals} = this.state;
        return(
            <div className="card-list">
                <div className="container">
                    <h1 className="page-title">Your Home All Around the World</h1>
                    <div className="row">
                        {
                            rentals.map((rental)=>{
                                return(
                                    <div key={rental._id} className="col-md-3">
                                        <div className="card bwm-card">
                                        <img 
                                        className="card-img-top" 
                                        src={rental.image}
                                        alt={rental.title} />
                                        <div className="card-body">
                                        <h6 className="card-subtitle mb-0 text-muted">
                                            {rental.shared} {rental.category} {rental.city}
                                        </h6>
                                        <h5 className="card-title big-font">
                                            {rental.title}
                                        </h5>
                                        <p className="card-text">
                                            ${rental.dailyPrice} per Night &#183; Free Cancelation
                                        </p>
                                        </div>
                                        </div>
                                    </div>
                                )
                            })
                        }
                        
                    </div>
                </div>
            </div>
        )
    }
}

export default RentalHome;

1

试试这个:

class First extends React.Component {
  constructor (props){
    super(props);

  }

  render() {
     const data =[{"name":"test1"},{"name":"test2"}];
    const listItems = data.map((d) => <li key={d.name}>{d.name}</li>;
    
    return (
      <div>
      {listItems}
      </div>
    );
  }
} 


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