英文:
How do I return a div and a variable from a Child component to a Parent component in Next js/React?
问题
我想创建一个 web 应用程序,在单击子组件生成的列表中的项目时,在父组件的 div 中显示图像。我认为在子组件中生成列表是最好的选择,因为它将是动态的。现在,我已经让列表生成并作为一个 div 发送回父组件,但如何包含一个指向被单击的图像的变量(例如 ID)呢?
也许需要将整个图像列表发送到子组件中,然后在那里生成列表?甚至将整个主组件保持在一个组件中?我对 React/NextJS 还不太熟悉,所以我真的需要一些指导。以下是代码,以便你了解正在发生的情况:
简化的父组件:
import Paintings from "./components/Paintings";
export default function Gallery() {
var images = require('/public/gallerij.json');
// 具有以下结构的 JSON 文件:
[
{
"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'>
{/* 根据 Paintings 中的变量在这里显示图像 */}
</div>
</div>
</main>
)
}
简化的子组件:
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>
)
}
希望这可以帮助你朝正确的方向前进,提前谢谢!
英文:
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!
答案1
得分: 1
我将翻译代码部分,如下所示:
const [activePaintingId, setActivePaintingId] = useState(null);
const currentPainting = images.find(
(image) => image.Number === activePaintingId
);
<div className="painting-list">
{images.map((block) => (
<div onClick={() => setActivePaintingId(block.Number)}>
<Paintings {...block} />
</div>
))}
</div>
<div className="gallery-image">
{activePaintingId !== null ? (
// 基于 Paintings 的变量在这里显示图像
// {currentPainting}
) : null}
</div>
<div className="painting-list">
{images.map((block) => (
<Paintings {...block} setActivePaintingId={setActivePaintingId} />
))}
</div>
export default function Paintings(props) {
return (
<div
className="painting-list-item"
key={props.Number}
value={props.number}
onClick={() => setActivePaintingId(props.Number)}
>
...
</div>
);
}
请注意,这是你提供的代码的中文翻译部分,没有其他内容。
英文:
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.
const [activePaintingId, setActivePaintingId] = useState(null);
const currentPainting = images.find(
(image) => image.Number === activePaintingId
);
Then the first option could be to wrap the Paintings
into a div
element and applying a onClick
there.
<div className="painting-list">
{images.map((block) => (
<div onClick={() => setActivePaintingId(block.Number)}>
<Paintings {...block} />
</div>
))}
</div>
Where you then have access to the current painting like so.
<div className="gallery-image">
{activePaintingId !== null ? (
// DISPLAY image here based on variable from Paintings
// {currentPainting}
) : null}
</div>
The second one is to pass the function down to the child if you don't want to have another div surrounding your paining.
<div className="painting-list">
{images.map((block) => (
<Paintings {...block} setActivePaintingId={setActivePaintingId} />
))}
</div>
Then in the child add the onClick
export default function Paintings(props) {
return (
<div
className="painting-list-item"
key={props.Number}
value={props.number}
onClick={() => setActivePaintingId(props.Number)}
>
...
</div>
);
}
And displaying the image will be the same.
Also you should not set a value
prop on a div
since value is not a valid attribute, see MDN div attributes.
答案2
得分: 0
在你的.map
函数中,我认为你想要将组件定义为<Paintings { ...block }>
,而不是Paintings(block)
。此外,要传递点击的卡片和相应的索引,你需要创建一个函数,例如onDelete(index) { console.log(index) }
,然后将其传递给组件,如<Paintings { ...block } onDelete={ onDelete } />
。现在它作为一个属性传递,在Paintings
组件内部,你可以使用传递给该块的索引调用它,例如onDelete(props.Index)
,这将调用父组件中的函数。
英文:
I think at first in your .map
function you want to define your components as <Paintings { ...block />
instead of Paintings(block)
furthermore the way to pass which card is clicked with which index is by passing a function so create a function like onDelete(index) { console.log(index) }
and pass this to the component like <Paintings { ...block } onDelete={ onDelete } />
now it is passed as a prop and within the Paintings
component you can call this with the index that is passed to the block so like onDelete(props.Index)
and it will call the function in the parent component.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论