0

I am using the React-Rails gem and accessing a json object items from a Rails controller.

Rails controller:

class ItemsController < ApplicationController
  def index
    @items = Item.all
    render json: @items
  end
end

My React App component accesses these items and attempts to pass it as a prop to a child component:

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            items: {},
            activeTab: 'items'
        };
    }

    componentDidMount() {
        $.getJSON('/items.json', (response) => { 
            this.setState({ items: response }) 
        });
    }

  render () {
        return (
            <div>
                <ItemsContent items={this.state.items}> 
            </div>
        );
  }
}

And this child component looks like this:

class ItemsContent extends React.Component {
  render () {           
    return (
      <div>
        <div>Items: {this.props.items}</div>
      </div>
    );
  }
}

ItemsContent.propTypes = {
  items: React.PropTypes.object
};

And I get this error:

react.js?body=1:1324 Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {}). 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 `ItemsContent`.

How do I get around this? Is there a way to easily use JSON objects in my React components?

Right now I tried wrapping the JSON object in an array:

            tabbedContent = <ItemsContent items={[this.state.items]}></ItemsContent>;

2 Answers2

0

Since this.state.items is an array, you are unable to dump out all the items in an array like that. You can use the javascript array API and iterate over the items and display them like so :

class ItemsContent extends React.Component {
  render () {           
    return (
      <div>
        {
             this.props.items.map(function(item) {
                 return <div> Item : {item} </div>
        }
      </div>
    );
  }
}

ItemsContent.propTypes = {
  items: React.PropTypes.object
};

If you are only getting back a single object every time then map will not work and you need to break out the object by property in order to display everything :

render () {           
        return (
          <div>
              <div> Item : {this.props.items.a} , {this.props.items.b}, {this.props.items.c} </div>
          </div>
        );
}
erichardson30
  • 4,984
  • 8
  • 26
  • 47
0

You can iterate over the list in render() of App Component. And create a React.Component Item for each of the items.

App.js

render () {
        return (
            <div>
                this.state.items.map( function(item){
                   <Item value={item} key={}> 
                });
            </div>
        );
  }

In Item.js

class Item extends React.Component {
  render () {           
    return (
      <div>
         return <div> Item : {this.props.value} </div>
      </div>
    );
  }
}

Item.propTypes = {
  value: React.PropTypes.object
};
Abhishek Kumar
  • 674
  • 1
  • 6
  • 15