简体   繁体   中英

How do I expand multiple cards in react with state?

I have a list of cards. After click on each card I want them to expand with little bit more info. I get the cards from the server and map them. To expand single card, not multiple, I've created a state editIndex which checks the id of the card so it could work correctly and expand specifically that card. I can't figure out, how do I expand one card and other at the same time. Because right now if I click on card, the other one which was expanded is collapsing.

  const [studentList, setStudentList] = useState();
  const [input, setInput] = useState(" ");
  const [editIndex, setEditIndex] = useState(null);
  const [suggestions, setSuggestions] = useState(null);


 const handleExpand = (id) => {
 setEditIndex((e) => (e === id ? null : id))};
 
return (
<div
  className="flex
  flex-col 
  w-4/5
  h-[800px]
  overflow-scroll
  scrollbar-hide
  border 
  bg-white 
  rounded-xl
  "
>
  <div>
    {studentList?.map(
      ({
        city,
        company,
        email,
        firstName,
        grades,
        id,
        lastName,
        pic,
        skill,
      }) => (
        <div
          key={uuidv4()}
          onClick={(e) => handleExpand(id)}
          className="flex  border-b-2 py-2 px-7 xl:px-12 cursor-pointer
            mb-2 max-h-96 transition transform ease duration-200;
            "
        >
          <div className="flex items-center ">
            <img
              src={pic}
              className="flex items-center border rounded-full object-cover w-  [100px] h-[100px]"
            />
          </div>
          <div className="ml-10 superTest ">
            <p className="font-bold text-4xl">
              {firstName} {lastName}
            </p>
            <p>E-mail: {email}</p>
            <p>Company: {company}</p>
            <p>Skill: {skill}</p>
            <p>Average: {grades}% </p>

            {editIndex === id && (
              <div>
                <p>1</p>
                <p>2</p>
                <p>3</p>
                <p>4</p>
                <p>5</p>
              </div>
            )}
          </div>
        </div>
      )
    )}
  </div>
</div>
  );
    }

 export default Card;

Instead of editIndex , have a Set of the id values of expanded cards:

const [editing, setEditing] = useState(new Set());

Then, to expand/contract a card (sadly, Set has no built-in toggle method):

const handleExpand = (id) => {
    setEditing(editing => {
        // Copy the set
        editing = new Set(editing);
        if (editing.has(id)) {
            // Already editing, stop editing
            editing.delete(id);
        } else {
            // Not editing, start
            editing.add(id);
        }
        return editing;
    });
};

To determine whether a card is expanded, it's editing.has(id) :

{editing.has(id) && (
  <div>
    <p>1</p>
    <p>2</p>
    <p>3</p>
    <p>4</p>
    <p>5</p>
  </div>
)}

Try to use an array or map of expanded cards:

const [editIndex, setEditIndex] = useState([]);
...
const handleExpand = (id) => {
  setEditIndex((e) => (e.includes(id) ? e.filter(i => i !== id) : [...e, id]))
};
...
{editIndex.includes(id) && (
          <div>
            <p>1</p>
            <p>2</p>
            <p>3</p>
            <p>4</p>
            <p>5</p>
          </div>
)}

You should state with an object and keep expanded card ids in the object. Using object instead of an array you avoid loop to filter the array

  import React, { useState } from 'react';
  
  function Card() {
    const [studentList, setStudentList] = useState();
    const [editIndex, setEditIndex] = useState({});

    const handleExpand = (id) => {
        setEditIndex((e) => (e === id ? null : id))
        setEditIndex({id: !editIndex[id]});
    };

    return studentList.map((student, index) => 
        <div onClick={() => handleExpand(index)} className={`otherClassNames ${editIndex[index]?"expanded":"collapsed"}`}>
            {JSON.stringify(student)} // render student data
        </div>
        );
  }
  
  export default Card;

On the other hand, you can use the Collapse component of the Ant Design library. So leave the collapse issue them.

https://ant.design/components/collapse/

and other complicated components are available in the library use should check out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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