Unable to render JSON data in react component

By : Chakri
Source: Stackoverflow.com
Question!

I am trying to parse some JSON from an Ajax call to display it a table using react datatable component. The problem which I am facing is that when I try to put the data in a state variable using set state method, I am not able to access the required data. This is what the JSON looks like:

{
  "Search": [
    {
      "Title": "Star Wars: Episode IV - A New Hope",
      "Year": "1977",
      "imdbID": "tt0076759",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BOTIyMDY2NGQtOGJjNi00OTk4LWFhMDgtYmE3M2NiYzM0YTVmXkEyXkFqcGdeQXVyNTU1NTcwOTk@._V1_SX300.jpg"
    },
    {
      "Title": "Star Wars: Episode V - The Empire Strikes Back",
      "Year": "1980",
      "imdbID": "tt0080684",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BMjE2MzQwMTgxN15BMl5BanBnXkFtZTcwMDQzNjk2OQ@@._V1_SX300.jpg"
    },
    {
      "Title": "Star Wars: Episode VI - Return of the Jedi",
      "Year": "1983",
      "imdbID": "tt0086190",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BMTQ0MzI1NjYwOF5BMl5BanBnXkFtZTgwODU3NDU2MTE@._V1._CR93,97,1209,1861_SX89_AL_.jpg_V1_SX300.jpg"
    },
    {
      "Title": "Star Wars: The Force Awakens",
      "Year": "2015",
      "imdbID": "tt2488496",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BOTAzODEzNDAzMl5BMl5BanBnXkFtZTgwMDU1MTgzNzE@._V1_SX300.jpg"
    },
    {
      "Title": "Star Wars: Episode I - The Phantom Menace",
      "Year": "1999",
      "imdbID": "tt0120915",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BMTQ4NjEwNDA2Nl5BMl5BanBnXkFtZTcwNDUyNDQzNw@@._V1_SX300.jpg"
    },
    {
      "Title": "Star Wars: Episode III - Revenge of the Sith",
      "Year": "2005",
      "imdbID": "tt0121766",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BNTc4MTc3NTQ5OF5BMl5BanBnXkFtZTcwOTg0NjI4NA@@._V1_SX300.jpg"
    },
    {
      "Title": "Star Trek",
      "Year": "2009",
      "imdbID": "tt0796366",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BMjE5NDQ5OTE4Ml5BMl5BanBnXkFtZTcwOTE3NDIzMw@@._V1_SX300.jpg"
    },
    {
      "Title": "Star Wars: Episode II - Attack of the Clones",
      "Year": "2002",
      "imdbID": "tt0121765",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BMTY5MjI5NTIwNl5BMl5BanBnXkFtZTYwMTM1Njg2._V1_SX300.jpg"
    },
    {
      "Title": "Star Trek Into Darkness",
      "Year": "2013",
      "imdbID": "tt1408101",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BMTk2NzczOTgxNF5BMl5BanBnXkFtZTcwODQ5ODczOQ@@._V1_SX300.jpg"
    },
    {
      "Title": "Star Trek: First Contact",
      "Year": "1996",
      "imdbID": "tt0117731",
      "Type": "movie",
      "Poster": "http://ia.media-imdb.com/images/M/MV5BMTg4OTYwODY4MF5BMl5BanBnXkFtZTgwNTg2NjIyMDE@._V1_SX300.jpg"
    }
  ],
  "totalResults": "2846",
  "Response": "True"
}

"data.Search" should gives me an array of objects. This is not being sent to the data table component. Instead, if I try to somehow display "data.totalResults" it works because it throws single value. Or if the same array of objects is sent thru a local variable, it works. Please help me as I am new to React and this really is taking a lot of time! Any help appreciated in advance!

<body>
  <div id="container"></div>
  <script type="text/babel">

var tableColumns = [
   { 'title': 'Title', 'prop': 'Title' },
   { 'title': 'Year', 'prop': 'Year' }
 ];

var destination = document.querySelector("#container");
var Buildrules = React.createClass({

  getInitialState: function() {
        return {data: {}};
      },

  loadData: function(){
    $.ajax({
      url: 'http://www.omdbapi.com/?s=star&r=json&plot=short',
      success: function(data){
        console.log(data);
        this.setState({data: data});
        console.log(this.state.data.Search);
      }.bind(this)
    })

  },

componentWillMount: function(){
  this.loadData();

},
componentDidMount:function(){

},
render:function(){

  return (
    React.createElement(ReactDataComponents.DataTable, {
      keys: 'id',
      columns: this.props.col,
      initialData: this.state.data.Search, //Here, "data.Search" should give an array of objects but i am facing issue. If the same data is fed using a local variable, it works!
      initialPageLength: 5,
      initialSortBy: { prop: 'Title', order: 'descending'}
    })

        );
  }
});

ReactDOM.render(
  <div id="blah">
    <Buildrules col = {tableColumns} />
  </div>,
  destination
);


</script>


</body>
By : Chakri


Answers
Here is your solution: https://jsfiddle.net/lustoykov/fpfuuchj/1/

There are a few things that you have missed:

  • when you log your result the first time, it is undefined because you perform async request to fetch the data. This is why you need to check if its present and only then render it.
  • Also you log like console.log("this.state.data.Search" + this.state.data.Search). It should be: console.log("this.state.data.Search", this.state.data.Search)
  • Once data is there, you can see your search result
  • (Optional) Please bear in mind that Ajax requests are performed in componentDidMount as suggested in react's docu

If you don't want to display the data, but pass it to a DataTable component, instead of

const searches = this.state.data.Search ? this.state.data.Search.map((searchResult, index) => <h1 key={index}> {searchResult.Title} </h1>) : ""

simply have

const searches = this.state.data.Search ? this.state.data.Search.map(searchResult => <DataTable tableColumns={searchResult} />) : ""

This will display your <DataTable /> components once data is fetched.

By : leo


This video can help you solving your question :)
By: admin