I want to build a webapp that displays the image in a div of the Parent component when clicking on an item in the list generated by the child component. I figured it was best to generate the list in a child component, as it will be dynamic. Now, I have it working that the list is being generated and sent back to the parent component as a div, but how do I include a variable (e.g. the ID) that points to the image that is clicked?
Is it maybe necessary send the whole image list to the child component, and generate the list there? Maybe even the whole main to keep it in one component? I’m pretty new to React/ NextJS so I could really use some guidance. Here is the code to give you an idea of what’s going on:
Simplified parent component:
import Paintings from "./components/Paintings";
export default function Gallery() {
var images = require('/public/gallerij.json');
// Json file with this structure:
[
{
"Number": 1,
"Title": "Moments of Magic",
"Size": "70x50cm",
"Paint": 1,
"Sold": 1
},
{
"Number": 2,
"Title": "The lady in red",
"Size": "70x50cm",
"Paint": 1,
"Sold": 0
}]
return (
<main>
<div className='left-main'>
<header className='top-section'>
<h3 className='top-section-text'>Select a painting:</h3>
</header>
<div className='painting-list'>
{images.map(block => Paintings(block))}
</div>
</div>
<div className='right-main'>
<div className='gallery-image'>
// DISPLAY image here based on variable from Paintings
</div>
</div>
</main>
)
}
Simplified Child Component:
export default function Block(props) {
return (
<div className='painting-list-item' key={props.Number} value={props.number}>
<div className='title-list-item'>
<h2>{props.Title}</h2>
</div>
<div className='sold-list-item'>
<p className={`${props.Sold ? "sold" : "not-sold"}`}>{props.Sold ? 'Sold' : 'Available'}</p>
</div>
<div className='size-list-item'>
<p>{props.Size}</p>
</div>
<div className='image-list-item'>
<img className="painting-list-item-img" src={`/images/${props.Number}.jpg`} width={50} height={50}/>
</div>
</div>
)
}
Hopefully you guys can point me in the right direction, thank you in advance!
2
Answers
I think at first in your
.map
function you want to define your components as<Paintings { ...block />
instead ofPaintings(block)
furthermore the way to pass which card is clicked with which index is by passing a function so create a function likeonDelete(index) { console.log(index) }
and pass this to the component like<Paintings { ...block } onDelete={ onDelete } />
now it is passed as a prop and within thePaintings
component you can call this with the index that is passed to the block so likeonDelete(props.Index)
and it will call the function in the parent component.I would create some kind of state to track which painting should be displayed. And a derived variable which will hold the currently selected painting.
Then the first option could be to wrap the
Paintings
into adiv
element and applying aonClick
there.Where you then have access to the current painting like so.
The second one is to pass the function down to the child if you don’t want to have another div surrounding your paining.
Then in the child add the
onClick
And displaying the image will be the same.
Also you should not set a
value
prop on adiv
since value is not a valid attribute, see MDN div attributes.