anshul
anshul

Reputation: 791

How can I change the text of a button based on click if is looped inside a map function?

I am mapping over a series of cards in a form component like this :

```

{links?.map((i,j) => (
  <main className={styles["card-container"]} key={j}>
    <Card
        url={i?.url}
        shortenUrl={i?.shorten}
    />
  </main>
))}

```

That Card renders a URL link, a shortened link and a button that says "click"

<div>
  <div>{url}</div>
  <div>{shortenUrl}</div>
  <Button>Copy</Button>

</div>

The Button too is a reusable component,

  return (
    <>
      <button>{children}</button>
    </>
  )

What I want to do:

what I have tried :

Any solution to this?

Thanks for reading this far

Upvotes: 0

Views: 421

Answers (1)

Drew Reese
Drew Reese

Reputation: 203587

Add local state to each Card component, create a local click handler that toggles the state and calls any passed onClick handlers.

Example:

const [copy, setCopy] = useState();

const clickHandler = (e) => {
  setCopy(copy => !copy);
  // call any external click handler, pass onClick event object, etc...
};

<div>
  <div>{url}</div>
  <div>{shortenUrl}</div>
  <Button onClick={clickHandler}>
    {copy ? "Copied" : "Copy"}
  </Button>
</div>

Update

If you want only a single selected button at-a-time, then lift the state to the parent component render the Card components and pass as props the currently selected card and a callback to toggle the selected card.

Example:

const [selected, setSelected] = React.useState(null);

const toggleSelected = index => {
  // toggle null if deselecting current selected,
  // otherwise set selected as new index
  setSelected(selected => selected === index ? null : index);
};

...

{links?.map((i, index) => (
  <main className={styles["card-container"]} key={index}>
    <Card
      url={i?.url}
      shortenUrl={i?.shorten}
      selected={selected === index}
      onClick={() => toggleSelected(index)}
    />
  </main>
))}

...

const Card = ({ url, shortenUrl, selected, onClick }) => {
  ...

  return (
    ...

    <div>
      <div>{url}</div>
      <div>{shortenUrl}</div>
      <Button onClick={onClick}>
        {selected ? "Copied" : "Copy"}
      </Button>
    </div>

    ...
  );
};

Upvotes: 1

Related Questions