简体   繁体   English

React.js:单击列表中的项目时如何更改图标?

[英]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.我正在尝试实现一个逻辑,根据单击的项目, arrow down图标更改为arrow-up ,如果用户第二次单击同一行应该再次更改。
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任何帮助将不胜感激

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;

You want to toggle change the selectedIndex depending on whether the clicked item is already open.您想根据单击的项目是否已打开来切换更改selectedIndex The better way would be to move the Item to a separate component that has its own open state:更好的方法是将Item移动到具有自己open状态的单独组件:


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>
  );
}

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 .发生这种情况是因为您的图标仅在selectedIndex === i时才会更改,这意味着,只有您单击的行将是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.在这种情况下,一个不错的方法是在defaultListData中设置另一个变量,如标志,并检查它以呈现正确的图标。

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
  }
];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM