1

everyone thanks for the help!

I have looked at several similar questions but have not been able to extrapolate their answers to solve my problem.

I am using a ReactJS application to consume JSON from a website. I'm using the code from https://pusher.com/tutorials/consume-restful-api-react and changing it to fit my situation.

Currently, when I view index.js, I get the error "TypeError: assetList.assets is undefined." Given the the JSON and code below, what do I need to change to display a list of the assets and their properties?

I would like something like the display to look like the Desired Display below.

Desired Display.

There are two 2 assets:<br/>
  id: 1317 Filename: PROCESS_FLOW.pdf  
  id: 1836 Filename: 004527_FS.jpg



JSON consumed from website

{"totalNumberOfAssets":2,
"assets":[
  {"id":"1317","attributes":{"Filename":["PROCESS_FLOW.pdf"]}},
  {"id":"1836","attributes":{"Filename":["004527_FS.jpg"]}}
]}



components/assetList.js

import React from 'react'

const AssetList = ({assetList}) => {
  return (
    <div>
      There are {assetList.totalNumberOfAssets} assets:
      {assetList.assets.map((asset) => (
      <div>
        id: {asset.id}  filename: {asset.filename}
      </div>
      ))}
    </div>
  )
};

export default AssetList



App.js

import React, {Component} from 'react';
import AssetList from './components/assetList';

class App extends Component {
    render() {
        return (
            <AssetList assetList={this.state.assetList} />
        )
    }

    state = {
        assetList: []
    };

    componentDidMount() {
        fetch('http://ligitaddress/api/v1/asset')
            .then(res => res.json())
            .then((data) => {
                this.setState({ assetList: data })
            })
            .catch(console.log)
    }
}

export default App;



index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
1
  • 1
    what's the initial value of this.state.assetList? you might have to set it to an empty value to begin with. My guess is It's trying to do assetList.assets.map before assetList data is returned from the fetch. Commented Dec 4, 2019 at 19:45

2 Answers 2

1

On your first render, the value of this.state.assetList is an array:

state = {
    assetList: []
};

However you are passing it into <AssetList>

const AssetList = ({assetList}) => {
  return (
    <div>
      There are {assetList.totalNumberOfAssets} assets:
      {assetList.assets.map((asset) => (
      <div>
        id: {asset.id}  filename: {asset.filename}
      </div>
      ))}
    </div>
  )
};

The line saying assetList.assets.map is trying to call map() on something that is undefined. (you can access the property assets on an array and it will be undefined) It seems like it expects assetList to be an object with an assets array in it, but in your parent component assetList is initialized to an array... in short you're confusing yourself as to what kind of data you expect to be where.

Either change your initial state to reflect how you expect it to be passed into <AssetList>:

state = {
    assetList: {
        assets: []
    }
};

And/or change your <AssetList> component to properly check its prop:

const AssetList = ({assetList}) => {
  return (
    <div>
      There are {assetList.totalNumberOfAssets} assets:
      {Array.isArray(assetList.assets) && assetList.assets.map((asset) => (
      <div>
        id: {asset.id}  filename: {asset.filename}
      </div>
      ))}
    </div>
  )
};
Sign up to request clarification or add additional context in comments.

2 Comments

Awesome! Thank you. I changed state to be assetList: { assets: [] }. and then accessed id with asset.id and filename with asset.attributes.Filename.
@jddsm Happy to help. Please mark one of the answers as accepted to indicate that the question has been resolved.
1

This is happening because your components/assetList.js is trying to access assetList.assets on assetList.assets.map without it being defined.

When the API request is made and has not returned yet, the assets on assetList have not being defined, since assetList on App.js is initialized to an empty array.

You can replace the line on components/assetList.js with assetList.assets && assetList.assets.map(...) and that should do it

Comments

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.