3

Code is the following:

   return (
    <MuiThemeProvider>
      <GridList>

      {singleProd.map(function(product) {
        // console.log(product)
        let fileID;

        try {
          api.GetFile(product.relationships.main_image.data.id)

          .then((file) => {
            fileID = file.data.link.href;
            console.log(fileID)

            return (
                <Tile name={product.name} id={product.id} link={fileID} key={product.id} />
            )

          })
        }

        catch(e){
          console.log('product has no main image');

          return (
              <Tile name={product.name} id={product.id} link={fileID} key={product.id} />
          )
        }

      })}
      </GridList>
    </MuiThemeProvider>
   )

Error is: Cannot read property '_currentElement' of null

The diagnosis so far is that nothing is being returned for the .map function, because the returns are each wrapped in try catch blocks respectively.

If you add a return outside the try catch, it will succeed.

Wondering how I should format this so that each of the objects in the .map is run through the try catch. If the try succeeds, then that jsx is returned and used. If it doesn't, then the catch jsx is returned and used.

Any ideas how I might restructure the code above?

Other relevant info:

  • using material UI Tiles
  • using external API calls which return an array of objects, hence the map
  • the tile for each object is returned and becomes part of the gridList.
Matthew Foyle
  • 53
  • 1
  • 6

1 Answers1

3

The try/catch is not really the issue here I think. A few things to consider:

  1. You should not do an API call inside the render function. That will cause it to request multiple times, anytime the component re-renders.
  2. Your API call is asynchronous, so you will need to wait for the response to get the data you want.

The asynchronous bit is what's causing the current error I believe, because the .map doesn't have any data until the request finishes.

--

What you should do is:

  1. Call the API from componentDidMount
  2. Use setState to set the response data in your components state, and then render that result.

Even better would be to use something like redux to maintain your application state.

Austin Greco
  • 32,997
  • 6
  • 55
  • 59
  • Thanks for answering, Austin! The reason I have done it this way is that we have an initial API call within the `componentDidMount` that retrieves a list of products as an array. We then need to take each product in the array, and grab the file link for that product with a further API call. We then use both the product info from the array, and the file links to create a tile for each individual product. – Matthew Foyle May 30 '17 at 18:38
  • 1
    I see -- in that case, both API calls should still be in the `componentDidMount`, they should just be combined in some way and added to the component's `state`. This will be much better than doing it in the render function. – Austin Greco May 30 '17 at 19:59