I started a new React
Project.
I created Images that I imported in:
import Tip1 from "./img/Tips1.png";
import Tip2 from "./img/Tips2.png";
import Tip22 from "./img/Tips2-2.png";
...
I put them into arrays:
const TIP1 = [{ img: Tip1 }];
const TIP2 = [{ img: Tip2 }, { img: Tip22 }, { img: Tip222 }, { img: Tip2222 }];
const TIP3 = [{ img: Tip3 }, { img: Tip31 }, { img: Tip32 }, { img: Tip33 }];
const TIP4 = [{ img: Tip4 }, { img: Tip42 }];
Created extra modal that pops up when we click on the images.
and I created a function that displays these arrays one by one by using .map
:
const Tips = () => {
const [isOpen, setIsOpen] = useState(false);
const [selectedImageData, setImageData] = useState({ img: "" });
const onImageClicked = (imageData) => {
setImageData(imageData);
setIsOpen(true);
};
//Unique ID
const getUID = () => {
return Math.ceil((Math.random() * 10000))
}
return (
<>
<div className="mt-5 mb-3">
<h2> TIP #1 </h2>{" "}
</div>
{TIP1.map((imageData) => {
return (
<div className="card tips--card mt-5 mb-5 me-5 ms-5 ms-auto me-auto" key={getUID()}>
<img
src={imageData.img}
alt="Vocab1"
className="card-img-top tips--img"
onClick={() => onImageClicked(imageData)}
/>
<div className="card-body"></div>
</div>
);
})}
<div className="row ms-auto me-auto">
<div className="mt-5 mb-3">
<h2> TIP #2 </h2>{" "}
</div>
{TIP2.map((imageData) => {
return (
<div className="card tips--card mt-5 mb-5 me-5 ms-5 ms-auto me-auto" key={getUID()}>
<img
src={imageData.img}
alt="Vocab1"
className="card-img-top tips--img"
onClick={() => onImageClicked(imageData)}
/>
<div className="card-body"></div>
</div>
);
})}
...
And in the end of the function I added the Modal:
...
{isOpen && (
// bind the selected image data state to a data prop on Modal
<Modal
// data ={isOpen }
image={selectedImageData.img}
// close the modal
setIsOpen={setIsOpen}
/>
)}
</>
);
};
It works, but it is not scalable at all, and looks goofy with this much code.
My plan is to create a nested loop by using an extra array:
const TIPS = [
{ TIP: TIP2 },
{ TIP: TIP3 },
{ TIP: TIP4 },
{ TIP: TIP5 },
{ TIP: TIP6 },
{ TIP: TIP7 },
{ TIP: TIP8 },
{ TIP: TIP9 },
];
And this is where I stuck. My best shot was creating an other map so far but it didn't bring closer to the solution.
My question: How could I create a Nested loop that displays the images from the array of an array?
CodePudding user response:
I see what you want, you are already on the right track, all you need to do is to call the map
twice.
{TIP.map((TIPRow, i) => {
// this is each row
return (
<div key={"row" i}>
{TIPRow.map(imageData => {
// this is the image as in your code
}}
</div>
)
}}
As you said it's nested, you can replace div
with any other html structure you want, ex. tr
, or li
. This is up to you at this point.
NOTE: the challenge is to work with each bracket, [({
, so if it's first time, just write slowly, ex. only try to get the first loop working by printing out a row, and then work on second loop. Otherwise the level of bracket could cost you a day ;)
CodePudding user response:
It was a syntactical mistake. Basically, I didn't realize I needed to refer to the previous .map
in the second .map
and I assumed it will see it automatically.
{TIPS.map((TIPDATA) => {
return (
<div >
<div className="row mt-5">
<h2>STEP #{ counter }</h2>
{TIPDATA.TIP.map((imageData) => {
return (
<div className=" card tips--card mt-5 mb-5 me-5 ms-5 ms-auto me-auto" key={getUID()}>
<img
src={imageData.img}
alt="Vocab1"
className="card-img-top tips--img"
onClick={() => onImageClicked(imageData)}
key={getUID()}
/>
</div>
);
}
)
}
</div>
</div>
);
})}