在映射的卡片中单独切换动作

Toggling actions individually in cards mapped over

我有映射的卡片它们都有一个切换按钮菜单,我试图弄清楚如何单独定位菜单,因为它们由状态的单个部分控制,我什至不确定这是可能的。但是我觉得应该是吧?我创建了一个简单的 working example here。我不确定我是否可以使用它们的 ID 来单独定位它们,但我不确定如何实现它。任何建议都会有所帮助,谢谢!

1) 首先你不能用单一的布尔状态控制 Items 的所有状态,你可以创建 open 作为一个数组并且然后最初将其设置为 false.

const [open, setOpen] = useState(Array.from(Items, () => false));

2) 当你想切换特定元素时,你可以使用 index

onClick={() => toggle(idx)}

3) 那么你必须处理 2 种更新 newOpenState

的情况

案例:1:当你点击按钮后更新各自的状态。在这种情况下,您只是切换索引 idx

中存在的值
<Button
    isOpen={open[idx]}
    onClick={() => toggle( idx )}
    style={{
        width: "30px",
        height: "30px",
        marginTop: "25px",
        marginLeft: "10px"
    }}
/>

案例2:当你外部提供值时

<Col
    md="12"
    onClick={() => toggle( idx, false )}
    className="editCol"
>

所以这两种情况都可以用一个表达式来涵盖:

newOpenState[index] = value ?? !newOpenState[index];

以上语句的意思是,如果提供了 value(情况 2),那么您只需将值分配给 newOpenState[index]。如果您没有提供值(案例 1),那么它将是 undefined,您只需切换 newOpenState[index] 的值。我使用 Nullish coalescing operator (??) 如果左侧值是 undefinednull.

,则可以分配右侧值 ??

代码

import "./styles.css";
import { Card, Button, Col, Row } from "reactstrap";
import { useState } from "react";

const Items = [
  {
    name: "Test 1",
    ID: 1234
  },
  {
    name: "Test 2",
    ID: 4321
  },
  {
    name: "Test 3",
    ID: 3421
  }
];

export default function App() {
  const [open, setOpen] = useState(Array.from(Items, () => false));

  const toggle = (index, value) => {
    const newOpenState = [...open];
    newOpenState[index] = value ?? !newOpenState[index];
    setOpen(newOpenState);
  };

  return (
    <>
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
      <div style={{ display: "flex", justifyContent: "space-between" }}>
        {Items.map((item, idx) => (
          <Card
            key={idx}
            style={{
              border: "solid",
              borderColor: "#00000",
              margin: "5px",
              width: "150px",
              display: "flex",
              justifyContent: "center"
            }}
          >
            <h1>{item.name}</h1>
            <span style={{ display: "flex" }}>
              {!open[idx] ? (
                <Button
                  isOpen={open[idx]}
                  onClick={() => toggle(idx)}
                  style={{
                    width: "30px",
                    height: "30px",
                    marginTop: "25px",
                    marginLeft: "10px"
                  }}
                >
                  ...
                </Button>
              ) : (
                <Card
                  style={{
                    border: "solid 1px",
                    borderColor: "#00000",
                    margin: "5px"
                  }}
                >
                  <Row>
                    <Col md="12" className="closeMenu">
                      <span className="X" onClick={() => toggle(idx, false)}>
                        X
                      </span>
                    </Col>
                  </Row>
                  <Row>
                    <Col
                      md="12"
                      onClick={() => toggle(idx, false)}
                      className="editCol"
                    >
                      <span
                        className="editName"
                        onClick={() => setOpen(item.ID)}
                      >
                        Edit Name
                      </span>
                    </Col>
                  </Row>
                  <Row>
                    <Col md="12">
                      <span
                        className="deleteForm"
                        onClick={() => handleFormDelete(item.ID)}
                      >
                        Delete
                      </span>
                    </Col>
                  </Row>
                </Card>
              )}
            </span>
          </Card>
        ))}
      </div>
    </>
  );
}