Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

657
Visualizações
React.js: How to change icon when item in the list is clicked?

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

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

You need maintain state for each record check out below example

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";

function UserSettings() {
  const [open, setOpen] = useState(false);
  const [defaultListData, setDefaultListData] = useState([
    {
      name: "Dapibus ac facilisis in",
      selected: false
    },
    {
      name: "Morbi leo risus",
      selected: false
    },
    {
      name: "Porta ac consectetur ac",
      selected: false
    },
    {
      name: "Porta ac doesfvsaard  asdas",
      selected: false
    }
  ]);

  const handleClick = () => {
    setOpen(!open);
  };

  function handleTests(index) {
    let updateData = defaultListData.map((item, i) => {
      return index === i ? { ...item, selected: !item.selected } : item;
    });
    setDefaultListData(updateData);
  }

  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={category.selected ? faAngleDown : faAngleUp}
            />
          </ListGroup.Item>
        </ListGroup>
      ))}
    </div>
  );
}

export default UserSettings;
about 4 years ago · Juan Pablo Isaza Relatório

0

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>
  );
}
about 4 years ago · Juan Pablo Isaza Relatório

0

This is happening because your icon is being changed only when selectedIndex === i what means that, only the row that you've clicked will be faAngleDown .

In this case, a nice approach would be annother variable, like a flag, in the defaultListData and check it to render the right icon.

Ex.:

export const defaultListData = [
  {
    name: "Dapibus ac facilisis in",
    isOpen: false
  },
  {
    name: "Morbi leo risus",
    isOpen: false
  },
  {
    name: "Porta ac consectetur ac",
    isOpen: false
  },
  {
    name: "Porta ac doesfvsaard  asdas",
    isOpen: false
  }
];
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda