如何在 React 中更改映射数组的各个部分的状态

问题描述 投票:0回答:1

我有一个映射数组,设置为看起来像扑克牌。当我点击它们时,我需要它们“翻转”。现在,我的 onclick“有效”,状态/属性从“面朝上”变为“面朝下”,但它对所有 div 执行此操作,而不是对我单击的单个 div 执行此操作。

我认为也许它们都具有相同的使用状态可能是问题所在,或者我的条件语句需要更具体。我的反应很新,所以非常感谢任何帮助。

function DrawCards() {
  const [flip, setFlip] = React.useState("faceup");
  let values = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"];
  let heart = (
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="red" className="bi bi-heart-fill" viewBox="0 0 16 16">
      <path fillRule="evenodd" d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314" />
    </svg>
  );
  let spade = (
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="black" className="bi bi-suit-spade-fill" viewBox="0 0 16 16">
      <path d="M7.184 11.246A3.5 3.5 0 0 1 1 9c0-1.602 1.14-2.633 2.66-4.008C4.986 3.792 6.602 2.33 8 0c1.398 2.33 3.014 3.792 4.34 4.992C13.86 6.367 15 7.398 15 9a3.5 3.5 0 0 1-6.184 2.246 20 20 0 0 0 1.582 2.907c.231.35-.02.847-.438.847H6.04c-.419 0-.67-.497-.438-.847a20 20 0 0 0 1.582-2.907" />
    </svg>
  );
  let club = (
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="black" className="bi bi-suit-club-fill" viewBox="0 0 16 16">
      <path d="M11.5 12.5a3.5 3.5 0 0 1-2.684-1.254 20 20 0 0 0 1.582 2.907c.231.35-.02.847-.438.847H6.04c-.419 0-.67-.497-.438-.847a20 20 0 0 0 1.582-2.907 3.5 3.5 0 1 1-2.538-5.743 3.5 3.5 0 1 1 6.708 0A3.5 3.5 0 1 1 11.5 12.5" />
    </svg>
  );
  let diamond = (
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="red" className="bi bi-suit-diamond-fill" viewBox="0 0 16 16">
      <path d="M2.45 7.4 7.2 1.067a1 1 0 0 1 1.6 0L13.55 7.4a1 1 0 0 1 0 1.2L8.8 14.933a1 1 0 0 1-1.6 0L2.45 8.6a1 1 0 0 1 0-1.2" />
    </svg>
  );
  const flipCard = () => {
    setFlip("facedown");
    {
      flip === "facedown" && setFlip("faceup");
    }
  };

  const hearts = values.map((hcard, index) => (
    <div onClick={flipCard} key={index} face={flip} className="card">
      {hcard}
      {heart}
    </div>
  ));
  const spades = values.map((scard, index) => (
    <div key={index} className="card">
      {scard}
      {spade}
    </div>
  ));
  const clubs = values.map((ccard, index) => (
    <div key={index} className="card">
      {ccard}
      {club}
    </div>
  ));
  const diamonds = values.map((dcard, index) => (
    <div key={index} className="card">
      {dcard}
      {diamond}
    </div>
  ));
  console.log(Hearts);
  return (
    <div className="table">
      <div className="row">{hearts}</div>
    </div>
  );
}
reactjs onclick target
1个回答
0
投票

我想也许他们都有相同的

useState
可能是问题所在

是的,是的。

每种花色的每张牌都应该有独立的状态。但是,它不需要每个套装都有独立的功能,您可以拥有一个共享功能

renderCards
并将套装类型和所需的图标传递给该功能。

创建一个共享数组,其中值

initialFlipState
填充 13 个
"faceup"
字符串,然后您可以创建一个包含所有花色的对象状态,每个花色都有一个
initialFlipState
数组。

现在,在任何卡上单击,您将检查该卡是否有

faceup
,然后将其更改为
facedown
,反之亦然。

我添加了 CSS 类进行演示。

import React, { useState } from "react";

function DrawCards() {
  const initialFlipState = Array(13).fill("faceup");
  const [flipStates, setFlipStates] = useState({
    hearts: initialFlipState,
    spades: initialFlipState,
    clubs: initialFlipState,
    diamonds: initialFlipState,
  });

  let values = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"];

  let heart = (
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="red" className="bi bi-heart-fill" viewBox="0 0 16 16">
      <path fillRule="evenodd" d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314" />
    </svg>
  );
  let spade = (
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="black" className="bi bi-suit-spade-fill" viewBox="0 0 16 16">
      <path d="M7.184 11.246A3.5 3.5 0 0 1 1 9c0-1.602 1.14-2.633 2.66-4.008C4.986 3.792 6.602 2.33 8 0c1.398 2.33 3.014 3.792 4.34 4.992C13.86 6.367 15 7.398 15 9a3.5 3.5 0 0 1-6.184 2.246 20 20 0 0 0 1.582 2.907c.231.35-.02.847-.438.847H6.04c-.419 0-.67-.497-.438-.847a20 20 0 0 0 1.582-2.907" />
    </svg>
  );
  let club = (
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="black" className="bi bi-suit-club-fill" viewBox="0 0 16 16">
      <path d="M11.5 12.5a3.5 3.5 0 0 1-2.684-1.254 20 20 0 0 0 1.582 2.907c.231.35-.02.847-.438.847H6.04c-.419 0-.67-.497-.438-.847a20 20 0 0 0 1.582-2.907 3.5 3.5 0 1 1-2.538-5.743 3.5 3.5 0 1 1 6.708 0A3.5 3.5 0 1 1 11.5 12.5" />
    </svg>
  );
  let diamond = (
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="red" className="bi bi-suit-diamond-fill" viewBox="0 0 16 16">
      <path d="M2.45 7.4 7.2 1.067a1 1 0 0 1 1.6 0L13.55 7.4a1 1 0 0 1 0 1.2L8.8 14.933a1 1 0 0 1-1.6 0L2.45 8.6a1 1 0 0 1 0-1.2" />
    </svg>
  );

  const flipCard = (suit, index) => {
    setFlipStates((prevState) => ({
      ...prevState,
      [suit]: prevState[suit].map((state, i) => (i === index ? (state === "faceup" ? "facedown" : "faceup") : state)),
    }));
  };

  const renderCards = (suit, icon) =>
    values.map((card, index) => (
      <div onClick={() => flipCard(suit, index)} key={index} face={flipStates[suit][index]} className={`card ${flipStates[suit][index]}`}>
        {card} {icon}
      </div>
    ));

  return (
    <div className="table">
      <div className="row">{renderCards("hearts", heart)}</div>
      <div className="row">{renderCards("spades", spade)}</div>
      <div className="row">{renderCards("clubs", club)}</div>
      <div className="row">{renderCards("diamonds", diamond)}</div>
    </div>
  );
}

export default DrawCards;

这是 StackBlitz

上的一个工作示例
© www.soinside.com 2019 - 2024. All rights reserved.