Clafouti
Clafouti

Reputation: 4645

Loop and render an object in React.js

I'm trying to render an object inside an element (Panel element in react-bootstrap).

import React, { PropTypes } from 'react';
import { Panel } from 'react-bootstrap';

const NetworkDetail = React.createClass({
  render () {
    return (
      <Panel header="Network Details" bsStyle="info">
        {this.props.dataDetail && Object.keys(this.props.dataDetail).map(function(detail, id) {
            return <span key={id}>{this.props.dataDetail[detail]}</span>;
        }.bind(this))}
      </Panel>
    )
  }
})

export default NetworkDetail

But that doesn't work. The error thrown is

Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {self}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of 'NetworkDetail'.

What I don't understand is that if I use

return <span key={id}>{this.props.dataDetail.myProperty}</span>;

it works.

How can I render all the properties and values of my object ?

Upvotes: 1

Views: 9933

Answers (1)

Cheng Sieu Ly
Cheng Sieu Ly

Reputation: 1166

It looks to me that this component is a stateless/dumb component. So, you should begin by reading about how to write these kind of components to maximize efficiency: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions

Then, to fix your component, you should notice that

    {this.props.dataDetail && Object.keys(this.props.dataDetail).map(function(detail, id) {
        return <span key={id}>{this.props.dataDetail[detail]}</span>;
    }.bind(this))}

is just a conditional statement. Notice your '&&'. So, assuming that this.props.dataDetail is an object, you can rewrite this component like this:

import React, { PropTypes } from 'react';
import { Panel } from 'react-bootstrap';

const NetworkDetail = ({dataDetail}) => 
  <Panel header="Network Details" bsStyle="info">
    {
      Object.keys(dataDetail).filter(v => v !== '_links').map((detail, id) => <span key={id}>{dataDetail[detail]}</span>)
    }
  </Panel>

export default NetworkDetail;

Let me know if this works!

Upvotes: 8

Related Questions