I’m trying to implement a logic, where based on clicked item, arrow down
icon changes to arrow-up
and if user clicks 2nd time to the same row should again change.
I tried to trigger it based on the index of clicked item, but doesn’t work properly.
Also tried to change the icons based on boolean state change like here
const handleClick = () => { setOpen(!open); };
But this approach changes state for all icons in the state.
Here is the code and sandbox link.
import React, { useState } from "react"; import { ListGroup } from "react-bootstrap"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faAngleUp, faAngleDown } from "@fortawesome/free-solid-svg-icons"; export const defaultListData = [ { name: "Dapibus ac facilisis in" }, { name: "Morbi leo risus" }, { name: "Porta ac consectetur ac" }, { name: "Porta ac doesfvsaard asdas" } ]; function UserSettings() { const [open, setOpen] = useState(false); const [selectedIndex, setSelectedIndex] = useState(0); const handleClick = () => { setOpen(!open); }; function handleTests(index) { setSelectedIndex(index); } return ( <div> {defaultListData.map((category, i) => ( <ListGroup key={category.name} variant="flush"> <ListGroup.Item onClick={(e) => handleTests(i)} style={{ display: "flex", gap: "50px" }} > {category.name} <FontAwesomeIcon style={{ color: "green", cursor: "pointer" }} icon={selectedIndex === i ? faAngleDown : faAngleUp} /> </ListGroup.Item> </ListGroup> ))} </div> ); } export default UserSettings;
Any help will be appreciated
Advertisement
Answer
You want to toggle change the selectedIndex
depending on whether the clicked item is already open. The better way would be to move the Item
to a separate component that has its own open
state:
const Item = (props) => { const [open, setOpen] = useState(false); const handleClick = () => { setOpen((prev) => !prev); }; return ( <ListGroup.Item onClick={(e) => handleClick()} style={{ display: "flex", gap: "50px" }} > {props.category.name} <FontAwesomeIcon style={{ color: "green", cursor: "pointer" }} icon={open ? faAngleDown : faAngleUp} /> </ListGroup.Item> ); }; function UserSettings() { return ( <div> {defaultListData.map((category, i) => ( <ListGroup key={category.name} variant="flush"> <Item category={category} /> </ListGroup> ))} </div> ); }