首页 > 解决方案 > React array mapping, toggles all drop-downs on click, I want to open the dropdown for the clicked card only

问题描述

TextQuoteCard

    import React, {useRef, useState} from 'react'
    import {Link} from "react-router-dom";

    import {QuoteCardDropdown} from "../../utils/dropdowns";
    
    export const TextQuoteCard = () => {
    
        const [open, setOpen] = useState(false)
        const toggle = () => setOpen(!open)
        const [textQuote, setTextQuote] = useState([
        
            {
                userId: '123',
                userName: 'Tr',
                userImageUrl: 'https://qph.fs.quoracdn.net/main-thumb-892821828-200-lrcgeycqieflgsovvoxglqawinbcjhtv.jpeg',
                quoteId: 'TQ122',
                postDateTime: 'Fri',
                quoteAuthorId: '123',
                quoteAuthorName: 'Jhon Mart',
                quoteCategory: 'Motivational',
                quoteType: 'textQuote',
                quoteText: 'If there’s no market, about finding market opportunities, or creating opportunities. If there’s no market, then you need to grow one',
                quoteImageUrl: 'https://qph.',
                bookmarkStatus: 2,
                likesCount: 3300,
                commentsCount: 123,
                overallShareCount: 1203,
                fbShareCount: 423,
                twtShareCount: 1232,
                waShareCount: 1023,
                viewCount: 1923
            },
            {
                userId: '124',
                userName: 'nr',
                userImageUrl: 'https://qph.fi.jpeg',
                quoteId: 'TQ123',
                postDateTime: 'Fri',
                quoteAuthorId: '123',
                quoteAuthorName: 'Wall Mart',
                quoteCategory: 'Motivational',
                quoteType: 'textQuote',
                quoteText: 'Best thing to do. ',
                quoteImageUrl: '',
                bookmarkStatus: 1,
                likesCount: 3300,
                commentsCount: 123,
                overallShareCount: 1203,
                fbShareCount: 423,
                twtShareCount: 1232,
                waShareCount: 1023,
                viewCount: 1923
            }
            ])
        const handleBookmark = (event) => {
            console.log(event)
        }
        const idGetter = (id) =>{
            console.log(id)
        }
        const test = Object.keys(textQuote).map(item => item)
        console.log(test)
    
        return(
            <div>
                {
                    textQuote.map((quote) => (
                        <div className="QuoteCardPrimaryContainer" key={quote.quoteId}>
                          <div>{quote.userName}</div>
                           <div className="ddContainer">
                             <span className="QuoteCardEngagementActionButtonIconContainer">
                              <span className="QuoteCardEngagementActionButtonIcon"
                                onClick={() => toggle(!open)}
                               >
                                options
                              </span>
                             </span>                                                                           
                            {open && <QuoteCardDropdown targetLink={quote.quoteId}/>}
                           </div>
                          </div>
    
                    ))
                }
            </div>
        )
    }

**

QuoteCardDropdown.js

import React, {useState} from 'react'
import {Link} from "react-router-dom";

import '../../global/assets/css/dropdowns.css'

export const QuoteCardDropdown = (props) => {
    const [ddItems, SetDdItems] = useState([
        {
            ddOptionIcon: 'icon',
            ddOptionText: 'Share',
            ddOptionTip: 'Tip text goes here',
            ddOptionBorder: 'no',
            targetId: props.targetId,
            targetLink: props.targetLink
        },
        {
            ddOptionIcon: 'icon',
            ddOptionText: 'Bookmark',
            ddOptionTip: 'Tip text goes here',
            ddOptionBorder: 'no',
            targetId: props.targetId,
            targetLink: props.targetLink
        }
    ])
    return (
        <div>
            <div className="quoteCardDropdownPrimaryContainer">
            
                            <div className="quoteCardDropdownPrimaryBody">
                                <div className="quoteCardDropdownPrimaryBodyInner">
                                    {
                                        ddItems.map(item => (
                                            <Link to=
                                                      {
                                                          item.ddOptionText === 'Edit this Quote' ?
                                                              `${'edit/' + props.targetLink}` :
                                                          item.ddOptionText === 'Share' ?
                                                              `${'share/' + props.targetLink}` : ''
                                                      }
                                            >
                                                <div className="quoteCardDropdownContentWrapper">
                                                    <div className="quoteCardDropdownContentItem">
                                                        <div className="quoteCardDropdownItem" key={item.ddOptionText}>
                                                            {item.ddOptionText}
                                                        </div>
                                                    </div>
                                                </div>
                                            </Link>
                                        ))
                                    }
                                </div>
                            </div>
                        </div>
                        <div className="quoteCardPointer" data-placement='top'> </div>
          
        </div>

    )

}

I have array of objects mapping to which showed multiple card on-page/feed. each card has a dropdown that the user can perform several actions for the clicked card. think of FB feed or any other social media feed card that the user can click to open a dropdown and pick option for the card. I am trying to achieve something similar but the problem is when I click on the button to open the dropdown it toggles all the dropdowns for all the cards instead of opening the dropdown for the clicked card.

Expected Behavior: open the dropdown for the clicked card only.

标签: reactjsecmascript-6

解决方案


Change the open to take the id:

const [open, setOpen] = useState() // undefined is nothing open
const toggle = id => setOpen(open === id ? undefined : id) // close if currently open

// the JSX

return(
  <div>
  {textQuote.map((quote) => (
        <div className="QuoteCardPrimaryContainer" key={quote.quoteId}>
          <div>{quote.userName}</div>
          <div className="ddContainer">
            <span className="QuoteCardEngagementActionButtonIconContainer">
              <span className="QuoteCardEngagementActionButtonIcon"
                onClick={() => toggle(quote.quoteId)}>
                options
                </span>
              </span>                                                                           
              {open === quote.quoteId && <QuoteCardDropdown targetLink={quote.quoteId}/>}
            </div>
          </div>
        ))}
  </div>
)


推荐阅读