Jon
Jon

Reputation: 445

How Can I Render an Image From JSON Data Into A Table Row Using React?

I'm trying to create a table with React that will receive JSON data eventually (via HTTP request). I am currently storing the data in the state of my first component, and then rendering the table in my second component.

I would like each row in my table to contain an image of an album cover, followed by text data about the track, artist, and album title. For this post, I will include one row of my data so that you may see how it is stored in state.

I am currently unable to render an image stored as a string in state. What could I changed about my getRowsData() function in order to make this work? Or maybe I need to change how I am calling my image string? Any help or advice would be greatly appreciated.

The state (with image string as a .jpeg file) is found here:

import React, { Component, useState, Fragment } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import AudioPlayer from './AudioPlayer';
import Table from './Table/TrackInfo';
import '../components/AudioPlayer.css';
import '../adrian_trinkhaus.jpeg';

export default class PostContent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      tracklist: this.props.tracklist,
      data: [
        {
'Album Art': '../adrian_trinkhaus.jpeg', 
'Artist': 'The Olivia Tremor Control', 
'Track Title': 'The Opera House', 
'Album Title': 'Music From The Unrealized Film Script: Dusk At Cubist Castle'},
    ] 
    }
  }

  render() {
    console.log(this.props.tracklist)
    return (
      <Fragment>
        {/*Audio Player and Related*/}
        <AudioPlayer />
        <Link id='home-link' to='/' activeClassName='active'>Homepage</Link>
        <div className="word-content">
          <h2 className="show-title">{this.props.showTitle}</h2>
          <div className="episode-post-content">{this.props.content}</div>
          <Table data={this.state.data} />
          <div className="bottom-link">
            <Link id='home-link' to='/' activeClassName='active'>Homepage</Link>
          </div>
        </div>
      </Fragment>
    )
  }
}

The table is created here:

import React, { Component } from 'react';
export default class Table extends React.Component {

  constructor(props) {
    super(props);
    this.getHeader = this.getHeader.bind(this);
    this.getRowsData = this.getRowsData.bind(this);
    this.getKeys = this.getKeys.bind(this);
  }

  getKeys = function () {
    return Object.keys(this.props.data[0]);
  }

  getHeader = function () {
    var keys = this.getKeys();
    return keys.map((key, index) => {
      return <th key={key}>{key.toUpperCase()}</th>
    })
  }

  getRowsData = function () {
    var items = this.props.data;
    var keys = this.getKeys();
    return items.map((row, index) => {
      return <tr key={index}><RenderRow key={index} data={row} keys={keys} /></tr>
    })
  }

  render() {
    return (
      <div>
        <table>
          <thead>
            <tr>{this.getHeader()}</tr>
          </thead>
          <tbody>
            {this.getRowsData()}
          </tbody>
        </table>
      </div>

    );
  }
}
const RenderRow = (props) => {
  return props.keys.map((key, index) => {
    return <td key={props.data[key]}>{props.data[key]}</td>
  })
}

Upvotes: 0

Views: 2607

Answers (1)

Hadi Mir
Hadi Mir

Reputation: 5133

You have to use HTML <image> element to display images so in your RenderRow function try to do this modification

const RenderRow = (props) => {
  return props.keys.map((key, index) => {
    return(
    <td key={props.data[key]}>
    <img src={props.data.Album Art} alt="Album Art" className="yourCustomStyle"/>
    <div>{props.data.Artist}</div>
     <div>{props.data.Track Title}</div>
    </td>
  )})
}

TIP:

In Table class instead of binding this to every function you can convert those functions to arrow functions which binds this automatically to a function. It will make your code shorter and cleaner. So to convert a function into arrow function all you have to do is this

functionName = (arguments) => {
  console.log("This is an arrow function")
}

Do this to all your functions and remove this binding in the constructor.

Hope it helps

Upvotes: 1

Related Questions