【问题标题】:How do I create a card on button click?如何在按钮单击时创建卡片?
【发布时间】:2021-05-31 11:57:33
【问题描述】:

我已经学习了几天 React JS。它非常有趣并且简化了 JavaScript,至少在我看来是这样。我目前的目标是创建一个按钮,单击该按钮将创建一张新卡片,卡片中生成一个随机数。

我不知道如何添加 onClick= 功能以使其按照我的设想工作。目前,我的 index.js 文件中已编写了按钮的代码。 index.js 是我的主文件,它是我的 App 组件所在的位置。我看到人们使用一个名为 App.js 的文件,不知道为什么,但这是另一个问题。

目前我的按钮风格化如下。

const App = () => {
  return (
    <body>
      <header>
        <div className="ui buttons">
          <button className="ui button mb-1 mt-1">
            <i className="plus icon"></i>
            Add Card
          </button>
          <div className="or mb-1 mt-1"></div>
          <button className="ui positive button mb-1 mt-1">
            <i className="sort numeric down icon"></i>
            Sort All
          </button>
        </div>
      </header>

它们位于我页面顶部的标题容器中。如下图所示。

我希望能够单击“添加卡片”按钮,然后让它在我的卡片容器中创建一张新卡片。如下图。

您在上图中看到的当前卡片目前是硬编码的。我创建了一个 MainCard.js 组件,其中包含卡片的代码,包括随机生成的数字的功能和样式。

import "bootstrap/dist/css/bootstrap.css";
import React from "react";
import { Card, Button } from "react-bootstrap";

let getRandomNumber = function (min, max) {
  let getRandom = Math.floor(Math.random() * max + min);
  return getRandom;
};

const MainCard = () => {
  return (
    <Card>
      <Button
        className="ui mini red basic icon button"
        style={{
          position: "absolute",
          top: "0",
          right: "0",
        }}
      >
        <i
          className="red x icon"
          style={{
            position: "relative",
            top: "0",
            right: "0",
          }}
        ></i>
      </Button>
      <Card.Body>{getRandomNumber(0, 101)}</Card.Body>
    </Card>
  );
};

export default MainCard;

以前我在 AddCard.js 中执行 onClick 功能,但由于某种原因,我创建的警报既是在重新加载页面时生成的,也是在单击按钮时生成的。我无法弄清楚其中的原因,它已成为我还无法爬过的墙。我很确定我错过了一些简单的东西,但我就是不知道那是什么。有什么想法可以实现吗?

【问题讨论】:

  • 我没有看到你的提醒。
  • 警报已被删除,它目前不在我上面提供的代码中。
  • 如果您不使用它,将其包含在您的问题中会令人困惑。
  • 我把它作为我尝试过的一个例子。我很抱歉。

标签: javascript reactjs bootstrap-4 onclick card


【解决方案1】:

您需要使用useState()

例如。

import { useState } from "react";

export default function App() {
  const [{items}, setItems] = useState({ items: [] });
  const addItem = () => {
    items.push(<div key={items.length}>Hello</div>);
    setItems({ items: [...items] });
  };

  return (
    <div>
      <button onClick={addItem} />
      {items}
    </div>
  );
}

这将创建一个持久存储,您可以将值设置为在组件重建之间保留的值。存储中的对象有一个键“项目”,其中包含一个包含项目的数组。将您的状态放在一个带有描述内容的键的对象中很方便。如果您需要调试您的应用程序,这可以让您知道您正在查看的状态对象。

addItem() 回调会将一个新项目添加到处于状态的对象中。重要的是,该项目具有应该是唯一的关键属性。这有助于反应监控数组中元素的状态。

可以看上面代码的demohere

【讨论】:

  • 在返回
  • 此示例创建一个按钮,该按钮将不断向列表中添加新项目。如果您只想要一张卡片,请将其添加到 addItem() 中,然后确保在添加卡片后禁用或删除按钮。
  • 我正在传播这些项目,因为我忘记了 react 不是这样工作的。您无需担心展开运算符 (...)。
  • 你太棒了。是的,它正在代码演示中显示。我添加了我的 MainCard 组件来代替 Hello 文本。所以现在它创建了卡片,但它是在按钮内创建的。然后我意识到我可以在按钮之后删除 {item},就像你出现在那里一样,添加我的文本,在这种情况下是 Add Card,然后将 {item} 向下移动到我的卡片容器中。它完美地工作。你帮了我很多,我真的很感激你。
【解决方案2】:

正如 Charles Bamford 的回复所述,您必须使用 useState 方法。 useState 方法创建一个变量和一个设置该变量值的方法。每次你改变一个状态(使用它的 setter)时,React 都会检查代码并在它被使用的地方重新渲染。你需要这样的东西:

const App = () => {
  const [cards, setCards] = useState([]); // instantiate cards as a empty Array

  const addCard = () => {
    // create a new array with the old values and the new random one
    const newCards = [...cards, Math.floor(Math.random() * 100)];

    setCards(newCards);
  };

  const removeCard = (cardIndex) => {
    // create a new array without the item that you are removing
    const newCards = cards.filter((card, index) => index !== cardIndex);

    setCards(newCards);
  };

  return (
    <body>
      <header>
        <div className="ui buttons">
          <button className="ui button mb-1 mt-1" onClick={() => addCard()}>
            <i className="plus icon"></i>
            Add Card
          </button>
          <div className="or mb-1 mt-1"></div>
          <button
            className="ui positive button mb-1 mt-1"
            onClick={() => addCard()}
          >
            <i className="sort numeric down icon"></i>
            Sort All
          </button>
        </div>
      </header>
      <main>
        {cards.map((cardNumber, index) => (
          <MainCard number={cardNumber} onRemove={() => removeCard(index)} />
        ))}
      </main>
    </body>
  );
};

使用像这样的数组 [10, 15, 33],cards.map 会为你做这样的事情:

  <main>
    <MainCard number={cards[0]} onRemove={() => removeCard(0)} /> // 10
    <MainCard number={cards[1]} onRemove={() => removeCard(1)} /> // 15
    <MainCard number={cards[2]} onRemove={() => removeCard(2)} /> // 33
  </main>

我们将“number”和“onRemove”函数从 App 组件传递给 MainCard 组件。现在我们只需要从我们的 props 中获取它,就像这样:

const MainCard = (props) => {
  const { onRemove, number } = props

  return (
    <Card>
      <Button
        className="ui mini red basic icon button"
        style={{
          position: "absolute",
          top: "0",
          right: "0",
        }}
        onClick={() => onRemove()}
      >
        <i
          className="red x icon"
          style={{
            position: "relative",
            top: "0",
            right: "0",
          }}
        ></i>
      </Button>
      <Card.Body>{number}</Card.Body>
    </Card>
  );
};

export default MainCard;

【讨论】:

  • 我也在测试你的解决方案,但我得到了一个错误。无法读取未定义的属性“地图”。我正在网上搜索解决方案,但一直找不到解决问题的方法。知道这意味着什么吗?
  • 这是初始值吧?常量 [{ 卡片 }, setCards] = useState([]);因此它将值视为一个空数组。那 .map 不就行了吗?
  • 现在可以使用了。我看到上面更新的代码并测试了它。
  • 你能解释一下 removeCard 函数是什么吗?是不是要拆卡?目前它只是用一个新的替换 int。
  • 当然。我看到你的卡片有一个删除按钮,所以你必须将它从你的 App 组件传递到你的 MainCard 组件。你这样做的方式是将它传递给你的 MainCard 组件,如下所示: removeCard(index)} /> 在你的 MainCard 组件中,你必须从道具中获取它,比如这个: const MainCard = ({ onRemove }) => { return ( 然后你在删除按钮上调用它:
猜你喜欢
相关资源
最近更新 更多
热门标签