0

I am trying to iterate through image paths in a JSON file to show them in a browser, using "img" tag. Hardcoded values are working fine but when I am trying to change them to a variable according to this post:

https://stackoverflow.com/a/45334965/11788161

Below is my products.json file that contains data (i keep my assets folder in the same folder as App.tsx file):

{
    "data": [{
            "id": 1,
            "title": "T-shirts",
            "img": "./assets/images/products/product1/1.jpg",
            "cost": 30,
            "detailPage": {
                "productDetail": "white",
                "size": "S, M, L, XL, XXL"
            }
        },
        {
            "id": 2,
            "title": "T-shirts",
            "img": "./assets/images/products/product2/1.jpg",
            "cost": 40,
            "detailPage": {
                "productDetail": "black",
                "size": "S, M, L, XL, XXL"
            }
        }
    ]
}

And here is my code that is using this data (the commented line is a hardcoded value which returns valid a picrute in browser, but only for one "id"):

import React from "react";
import { data } from "./products.json";

interface IProps {
  id: number;
}

const MainProductDetail = (props: IProps) => {
  const { id } = props;
  return (
    <>
      <div>
        <img src={require(`${data[id].img}`)} alt="t-shirt" />
        {/* <img src={require("./assets/images/1.jpg")} alt="t-shirt" />  */} /* Commented line */
        <p> Product: {data[id].id}</p>
        <p>Cost: {data[id].cost}</p>
      </div>
    </>
  );
};

const App: React.FC = () => {
  return (
    <>
      <MainProductDetail id={0} />
      <MainProductDetail id={1} />
    </>
  );
};

export default App;

The MainProductDetail should show a picture according to id in JSON file but instead, I get the error:

ReferenceError: data is not defined
MainProductDetail
src/App.tsx:13
  10 | return (
  11 |   <>
  12 |     <div>
> 13 |       <img src={require(`${data[id].img}`)} alt="t-shirt" />
     | ^  14 |       {/* <img src={require("./assets/images/1.jpg")} alt="t-shirt" /> */}
  15 |       <p> Product: {data[id].id}</p>
  16 |       <p>Cost: {data[id].cost}</p>

EDIT: When I delete "{}" from import: import data from './products.json' I get following error when I highlight "data" variable:

Element implicitly has an 'any' type because expression of type 'number' can't be used to index type '{ "data": { "id": number; "title": string; "img": string; "cost": number; "detailPage": { "productDetail": string; "size": string; }; }[]; }'.
  No index signature with a parameter of type 'number' was found on type '{ "data": { "id": number; "title": string; "img": string; "cost": number; "detailPage": { "productDetail": string; "size": string; }; }[]; }'.

EDIT 2: When I console.log(data) using: "import data from './products.json' I get the following log in chrome dev tools:

Objectdata: Array(2)0: cost: 30detailPage: {productDetail: "white", size: "S, M, L, XL, XXL"}id: 1img: "./assets/images/1.jpg"title: "T-shirts"__proto__: Object1: cost: 40detailPage: {productDetail: "black", size: "S, M, L, XL, XXL"}id: 2img: "./assets/images/2.jpg"title: "T-shirts"__proto__: Objectlength: 2__proto__: Array(0)concat: ƒ concat()arguments: (...)caller: (...)length: 1name: "concat"__proto__: ƒ ()[[Scopes]]: Scopes[0]constructor: ƒ Array()copyWithin: ƒ copyWithin()entries: ƒ entries()every: ƒ every()fill: ƒ fill()filter: ƒ filter()find: ƒ find()findIndex: ƒ findIndex()flat: ƒ flat()flatMap: ƒ flatMap()forEach: ƒ forEach()includes: ƒ includes()indexOf: ƒ indexOf()join: ƒ join()keys: ƒ keys()lastIndexOf: ƒ lastIndexOf()length: 0map: ƒ map()pop: ƒ pop()push: ƒ push()reduce: ƒ reduce()reduceRight: ƒ reduceRight()reverse: ƒ reverse()shift: ƒ shift()slice: ƒ slice()some: ƒ some()sort: ƒ sort()splice: ƒ splice()toLocaleString: ƒ toLocaleString()toString: ƒ toString()unshift: ƒ unshift()values: ƒ values()Symbol(Symbol.iterator): ƒ values()Symbol(Symbol.unscopables): {copyWithin: true, entries: true, fill: true, find: true, findIndex: true, …}__proto__: Object__proto__: constructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()

Do you know what might cause this error? Thanks for the help in advance.

  • I think this error might hiding the real problem. When you remove the image tag for moment, does `

    Product: {data[id].id}

    ` display "Product: 1" and "Product: 2" to the screen?
    – Jake Worth Sep 10 '19 at 19:28
  • Can you import it like ```import jsondata from "./products.json";``` and console log it? Are you using webpack? – joseluismurillorios Sep 10 '19 at 19:33
  • EDIT: Yes I am using webpack. When I delete a line with "img" tag I see the correct output: "Product: 1 Cost: 30 Product: 2 Cost: 40" –  Sep 10 '19 at 19:36
  • I added an edit to post with an error when I change to: import data from './products.json' –  Sep 10 '19 at 19:41
  • I am using create-react-app –  Sep 10 '19 at 19:42
  • Sorry, @joseluismurillorios I misunderstood the question. I edited a post with a log from chrome dev tools. I meanwhile changed the directory of images to: './assets/images' in compare to code in post to simplify. –  Sep 10 '19 at 19:48

1 Answers1

0

In the end, I went with this solution:

https://stackoverflow.com/a/54024418/11788161

I created ".tsx" file that is a copy of data in my .json file with "require" added in front of my image paths:

const data3 = [
  {
    id: 1,
    title: "T-shirts",
    img: require("./assets/images/1.jpg"),
    cost: 30,
    detailPage: {
      productDetail: "white",
      size: "S, M, L, XL, XXL"
    }
  },
/... rest of data .../
export default data3;

And in my App.tsx:

/ ... /
         <img src={`${data3[id].img}`} alt="t-shirt" />
/ ... /

It's not an ideal solution because I had to copy data from JSON file to another file but it does the job.