Reputation: 791
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 :
form
component using prop drilling to the Button component, but it doesn't work as expected.Any solution to this?
Thanks for reading this far
Upvotes: 0
Views: 421
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>
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