1

I have in my state both an array of collections and an array of assets. What I'm trying to do now in my render method is map for every element in my collectionsarray an image that corresponds to the masterid. I am basically trying to find a way to access the asset.path within the collection mapping.

My initial thought was this: const assetpic = this.state.assetsarr.find(asset => asset.id === element.id) , but then I still need to find a way to use asset inside?


App.js

import React from 'react';
import './App.css';
import {collections} from "./data.js"
import {assets} from "./data.js"

class App extends React.Component {
    constructor() {
        super()

        this.state = {
           collectionsarr: collections,
           assetsarr: assets,
           clickedassets: []
        }
    }

    handleAssetsClick(id){
      const clickedassetsdata = this.state.assetsarr.filter(asset => asset.collectionId === id)
      this.setState({
        clickedassets: clickedassetsdata
      })
    }

    makeMaster(idclick){
      const themasteridnr = this.state.clickedassets.filter(masterpot => masterpot.id === idclick)[0].id
      const newcollections = this.state.collectionsarr.slice()
      const index = this.state.clickedassets.filter(masterpot => masterpot.id === idclick)[0].collectionId - 1
      newcollections[index].masterAssetId = themasteridnr
      this.setState({   
        ...this.state,
        collectionsarr: newcollections
      })
    }
  
  render(){

  return (
          <div className="App">
            <h1>Sitecore coding challenge</h1>
            
            <div className="left">
              {this.state.collectionsarr.map(element => 
                <div key={element.id}>
                  <p onClick={()=>this.handleAssetsClick(element.id)}>{element.name}</p>
                  <p>{element.masterAssetId}</p>

                 <img src={`./${asset.path}`} alt="pic"/>

                </div>
              )}
            </div>
          </div>
        )
  }
}

export default App

data.js

const collections = [
    {
        id: 1,
        name: "The Simpsons",
        masterAssetId: 13,
        tags: {
            name: "Cartoon",
            subTag: {
                name: "Simpsons family",
                subTag: {
                    name: "2014",
                },
            },
        },
    },
    {
        id: 2,
        name: "Super heroes",
        masterAssetId: 24,
        tags: {
            name: "DC Super heroes",
            subTag: {
                name: "2014",
            },
        },
    },
    {
        id: 3,
        name: "Toy story",
        masterAssetId: 31,
        tags: {
            name: "Disney",
            subTag: {
                name: "Pixar",
                subTag: {
                    name: "Original movie",
                    subTag: {
                        name: "2010",
                    },
                },
            },
        },
    },
    {
        id: 4,
        name: "Ninjago",
        masterAssetId: 42,
        tags: {
            name: "Ninja",
            subTag: {
                name: "Secret Ninja Force",
                subTag: {
                    name: "2017",
                },
            },
        },
    },
];

const assets = [
    {
        id: 11,
        name: "Homer Simpson",
        path: "Homer.jpg",
        collectionId: 1,
    },
    {
        id: 12,
        name: "Lisa Simpson",
        path: "Lisa.jpg",
        collectionId: 1,
    },
    {
        id: 13,
        name: "Bart Simpson",
        path: "Bart.jpg",
        collectionId: 1,
    },
    {
        id: 14,
        name: "Marge Simpson",
        path: "Marge.jpg",
        collectionId: 1,
    },
    {
        id: 15,
        name: "Grampa Simpson",
        path: "Grampa.jpg",
        collectionId: 1,
    },
    {
        id: 16,
        name: "Maggie Simpson",
        path: "Maggie.jpg",
        collectionId: 1,
    },
    {
        id: 21,
        name: "Green Lantern",
        path: "Green lantern.jpg",
        collectionId: 2,
    },
    {
        id: 22,
        name: "Flash",
        path: "Flash.jpg",
        collectionId: 2,
    },
    {
        id: 23,
        name: "Batman",
        path: "Batman.jpg",
        collectionId: 2,
    },
    {
        id: 24,
        name: "Superman",
        path: "Superman.jpg",
        collectionId: 2,
    },
    {
        id: 31,
        name: "Buzz Lightyear",
        path: "Buzz.jpg",
        collectionId: 3,
    },
    {
        id: 32,
        name: "Alien",
        path: "Alien.jpg",
        collectionId: 3,
    },
    {
        id: 41,
        name: "Spinjitzu training Nya",
        path: "Nya.jpg",
        collectionId: 4,
    },
    {
        id: 42,
        name: "Master Wu",
        path: "Wu.jpg",
        collectionId: 4,
    },
    {
        id: 43,
        name: "Lloyd",
        path: "Lloyd.jpg",
        collectionId: 4,
    },
];

enter image description here

charlesbxl
  • 85
  • 8

2 Answers2

1

Just create a new method getAssetPath

...
getAssetPath = (masterAssetId) => {
  const asset = this.state.assetsarr.find(x => x.id === masterAssetId)
  return asset ? `./${asset.path}` : '';
}

And pass it to the src in your img element

...
<img src={require(this.getAssetPath(element.masterAssetId))} alt="pic"/>
...

OR if you have to display all the images for each collection you have to filter assets for each specific collection and map again

<div className="left">
  {this.state.collectionsarr.map((element) => (
    <div key={element.id}>
      <p onClick={() => this.handleAssetsClick(element.id)}>{element.name}</p>
      <p>{element.masterAssetId}</p>

      {this.state.assetsarr.filter(x => x.collectionId === element.id).map((asset) => (
        <img src={require(`./${asset.path}`)} alt="pic" />
      ))}
    </div>
  ))}
</div>;
Rostyslav
  • 2,606
  • 9
  • 17
  • what do you think is the best practise way of doing this? Just like you did above or like aravind did below? – charlesbxl Jun 26 '20 at 12:25
  • My answer is the best practice, of course :) And here is my logical argument: if you hide the logic in a separate function (as I did it) you can either handle exceptions / change logic / do some additional processing and DO NOT touch the template code. This is called [single responsibility](https://en.wikipedia.org/wiki/Single-responsibility_principle) according to Robert C. Martin's [Clean Code book](https://www.amazon.com/Robert-Martin-Clean-Code-Collection-ebook/dp/B00666M59G) – Rostyslav Jun 26 '20 at 13:10
  • Thanks when using the first option I get this error: ./src/App.js Line 53:34: 'getAssetPath' is not defined no-undef => any idea why? – charlesbxl Jun 26 '20 at 13:12
  • Make sure that you have added the `getAssetPath` method to the component class and access it with `this` keyword like this `pic` – Rostyslav Jun 26 '20 at 13:14
  • thanks bro, still no image appearing though: my images are in the same folder as App.js & data.js. Any idea why? – charlesbxl Jun 26 '20 at 13:16
  • @charlesbxl updated the answer: ```return asset ? `./${asset.path}` : '';}``` – Rostyslav Jun 26 '20 at 13:21
  • Try also to check the path. It might be `./${asset.path}` or ` `./src/${asset.path}` if you store images next to App.js – Rostyslav Jun 26 '20 at 13:29
  • Thanks but still not working...would you mind having another look? I added my project structure – charlesbxl Jun 26 '20 at 14:10
  • @charlesbxl Try using the `required` keyword to load the image. I have updated the answer. Also checkout this question https://stackoverflow.com/questions/34582405/react-wont-load-local-images – Rostyslav Jun 26 '20 at 14:41
1

in render you need to use your element to find the corresponding asset from your asset collection like this:

    render(){

  return (
          <div className="App">
            <h1>Sitecore coding challenge</h1>
            
            <div className="left">
              {this.state.collectionsarr.map(element =>{ 
             const asset = this.state.assets.find(asset=>asset.id===element.masterAssetId)
               return(
                <div key={element.id}>
                  <p onClick={()=>this.handleAssetsClick(element.id)}>{element.name} 
                   </p>
                  <p>{element.masterAssetId}</p>

                 <img src={`./${asset.path}`} alt="pic"/>

                </div>
               )}
              )}
            </div>
          </div>
        )
  }
aravind_reddy
  • 5,236
  • 4
  • 23
  • 39