0

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

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks - though I am still not able to get the image to render, only a broken image link with the alt text. I believe the image is Additionally, with the code below (see other comment), I am getting a table with one row, but the data is copied four times, so my data looks like: album_art | artist | track_title | album_title | (x4...) How do I modify the (key, index) arguments in your response to only generate one row with four table data entries, and do you know why the image is still not rendering? The path to the image is correct in the file structure.
``` const RenderRow = (props) => { return props.keys.map((key, index) => { return ( <Fragment> <td key={props.data[key]}></td> <img src={props.data.album_art} alt="Album Art" /> <td>{props.data.artist}</td> <td>{props.data.track_title}</td> <td>{props.data.album_title}</td> </Fragment> ) }) } ```
you are getting "only a broken image link with the alt text." because the< img /> tag is not able to locate the image. This happens because to use local images in react you have to import them first . Have a look at this stackoverflow.com/questions/39999367/…
Thank you - I can see the image now! The only issue now is that the data is copied four times in the row. I only have four columns, but the DOM is rendering four copies of the table data. Is this an issue with how the Render Row function? (below)
const RenderRow = (props) => { return props.keys.map((key, index) => { return ( <Fragment> <td key={props.data[key]}> <img src={props.data.album_art} width="90px" height="90px" alt="Album Art" /></td> <td>{props.data.artist}</td> <td>{props.data.track_title}</td> <td>{props.data.album_title}</td> </Fragment> ) }) }
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.