如何在Next.js/React中从子组件返回一个div和一个变量到父组件?

huangapple go评论140阅读模式
英文:

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 &quot;./components/Paintings&quot;;

export default function Gallery() {

    var images = require(&#39;/public/gallerij.json&#39;);
    // Json file with this structure:
    [
  {
    &quot;Number&quot;: 1,
    &quot;Title&quot;: &quot;Moments of Magic&quot;,
    &quot;Size&quot;: &quot;70x50cm&quot;,
    &quot;Paint&quot;: 1,
    &quot;Sold&quot;: 1
  },
  {
    &quot;Number&quot;: 2,
    &quot;Title&quot;: &quot;The lady in red&quot;,
    &quot;Size&quot;: &quot;70x50cm&quot;,
    &quot;Paint&quot;: 1,
    &quot;Sold&quot;: 0
  }]

    return (
            &lt;main&gt;
                &lt;div className=&#39;left-main&#39;&gt;
                    &lt;header className=&#39;top-section&#39;&gt;
                        &lt;h3 className=&#39;top-section-text&#39;&gt;Select a painting:&lt;/h3&gt;
                    &lt;/header&gt;
                    &lt;div className=&#39;painting-list&#39;&gt;
                        {images.map(block =&gt; Paintings(block))}
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;div className=&#39;right-main&#39;&gt;
                    &lt;div className=&#39;gallery-image&#39;&gt;
                        // DISPLAY image here based on variable from Paintings
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/main&gt;
    )
}

Simplified Child Component:

export default function Block(props) {

    return (
        &lt;div className=&#39;painting-list-item&#39; key={props.Number} value={props.number}&gt;
            &lt;div className=&#39;title-list-item&#39;&gt;
                &lt;h2&gt;{props.Title}&lt;/h2&gt;
            &lt;/div&gt;
            &lt;div className=&#39;sold-list-item&#39;&gt;
                &lt;p className={`${props.Sold ? &quot;sold&quot; : &quot;not-sold&quot;}`}&gt;{props.Sold ? &#39;Sold&#39; : &#39;Available&#39;}&lt;/p&gt;
            &lt;/div&gt;
            &lt;div className=&#39;size-list-item&#39;&gt;
                &lt;p&gt;{props.Size}&lt;/p&gt;
            &lt;/div&gt;
            &lt;div className=&#39;image-list-item&#39;&gt;
                &lt;img className=&quot;painting-list-item-img&quot; src={`/images/${props.Number}.jpg`} width={50} height={50}/&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    )
}

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) =&gt; image.Number === activePaintingId
);

Then the first option could be to wrap the Paintings into a div element and applying a onClick there.

&lt;div className=&quot;painting-list&quot;&gt;
  {images.map((block) =&gt; (
    &lt;div onClick={() =&gt; setActivePaintingId(block.Number)}&gt;
      &lt;Paintings {...block} /&gt;
    &lt;/div&gt;
  ))}
&lt;/div&gt;

Where you then have access to the current painting like so.

&lt;div className=&quot;gallery-image&quot;&gt;
  {activePaintingId !== null ? (
    // DISPLAY image here based on variable from Paintings
  // {currentPainting}
  ) : null}
&lt;/div&gt;

The second one is to pass the function down to the child if you don't want to have another div surrounding your paining.

&lt;div className=&quot;painting-list&quot;&gt;
  {images.map((block) =&gt; (
    &lt;Paintings {...block} setActivePaintingId={setActivePaintingId} /&gt;
  ))}
&lt;/div&gt;

Then in the child add the onClick

export default function Paintings(props) {
  return (
    &lt;div
      className=&quot;painting-list-item&quot;
      key={props.Number}
      value={props.number}
      onClick={() =&gt; setActivePaintingId(props.Number)}
    &gt;
      ...
    &lt;/div&gt;
  );
}

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 &lt;Paintings { ...block /&gt; 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 &lt;Paintings { ...block } onDelete={ onDelete } /&gt; 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.

huangapple
  • 本文由 发表于 2023年3月7日 23:09:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75663738.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定