【问题标题】:Add selected state to single button in react将选定状态添加到反应中的单个按钮
【发布时间】:2020-10-02 13:53:09
【问题描述】:

我正在尝试将选定状态添加到我的按钮,我遇到的问题是每次单击它时,当我只想更新单击的按钮时,它会更新每个按钮的状态。

此应用的工作方式是,当您添加书签时,按钮文本会从“添加”变为“已添加”,同时还会更改类别。

这是我的按钮组件

import React from "react";

import PropTypes from "prop-types";

const Button = ({ children, onClick, classname }) => {
  return (
    <button onClick={onClick} className={classname}>
      <span>{children}</span>
    </button>
  );
};

Button.propTypes = {
  children: PropTypes.any.isRequired,
  onClick: PropTypes.func.isRequired,
  classname: PropTypes.string.isRequired
};

export default Button;

这是我的卡片组件,这是使用按钮的地方。

import React, { useState } from "react";
import PropTypes from "prop-types";
import "../css/Card.scss";
import { useStyles } from "../cssInJs/buttonStyle";
import Button from "./Button";

function Card({ author, title, image, onClick, selected }) {
  const classes = useStyles();

  return (
    <div className="Card__item">
      <div className="Card__spacer">
        <span className="Card__item__authorStyle">{author}</span>
      </div>
      <div>
        <span className="Card__item__titleStyle">{title}</span>
      </div>

      <div>
        <Button
          classname={`${selected ? classes.selectedButton : classes.myButton}`}
          onClick={onClick}
        >
          {` ${selected ? "ADDED" : "ADD"}`}
        </Button>
      </div>
      <div className="Card__item__image">
        <img src={image} alt="article-img" />
      </div>
    </div>
  );
}

Card.propTypes = {
  author: PropTypes.string.isRequired,
  title: PropTypes.string.isRequired
};

export default Card;

最后,这两个组件在布局组件中相遇:

import React, { useState } from "react";
import useFetch from "../hooks/useFetch";
import "../css/Layout.scss";
import Card from "./Card";
import BookmarksBar from "./BookmarksBar";

function Layout() {
  const { response } = useFetch();

  console.log(response);

  const [bookmarks, setBookmarks] = useState([]);
  const [selectedButton, setSelectedButton] = useState(false);

  function handleAddBookMark(title) {
    if (!bookmarks.includes(title)) {
      setBookmarks([...bookmarks, title]);
      setSelectedButton(true);
    } else {
      return false;
    }
  }

  function handleRemoveBookmark(val) {
    var index = bookmarks.indexOf(val);

    if (index > -1) {
      setBookmarks(bookmarks => bookmarks.filter((img, i) => i !== index));
    }
  }

  if (!response || response.length === 0) {
    return <div> Loading...</div>;
  } else {
    return (
      <div className="Layout__container">
        <div className="Layout__container__mainColumn">
          {response.data.articles.map((article, i) => (
            <Card
              key={i}
              author={article.author}
              title={article.title}
              image={article.urlToImage}
              onClick={() => handleAddBookMark(article.title)}
              selected={selectedButton}
            />
          ))}
        </div>
        <div className="Layout__container__rightColumn">
          <div className="Layout__container__rightColumn__customHr" />
          <div className="Layout__container__rightColumn__bookmarks">
            <span>Your bookmarks</span>
            <p>Articles you bookmark will be added to this list</p>
          </div>
          <BookmarksBar data={bookmarks} onClick={handleRemoveBookmark} />
        </div>
      </div>
    );
  }
}

export default Layout;

按钮状态由selectedButton 值控制。每次我单击由handleAddBookmark 函数触发的按钮时,它会将selectedButton 设置为true,但问题是当我只希望单击的按钮为true 时,它会将列表中的每个按钮设置为真.我如何做到这一点?

【问题讨论】:

  • 您有一个值,用于跟踪是否选择了多个值之一。那是你的问题。也许相反, selected 应该是一个包含所选项目 id 的数组?然后,当您选择时,将 id 添加到数组中,否则删除。然后在你的按钮选择的道具中,你可以像selected.includes(item.id)
  • @RogerBanks 您是否要求您的 Card 组件为任何 setSelected 更新一次又一次地重新渲染?如果是这样,那是因为 handleAddBookMark 方法被作为道具传递,而没有被缓存。您可以使用useCallback 来解决此问题。
  • 有道理.. szczocik 可以提供一个例子吗?

标签: reactjs


【解决方案1】:

bookmarks 中,而不是只存储标题推送 ID。在selected 中检查该id 是否已经在bookmarks 数组中。如果存在则返回选中的 true 否则返回 false。

&lt;BookmarksBar&gt; 组件中也更改了逻辑,因为现在您将传递包含标题和ID 的对象。在那里显示标题。并在 handleRemoveBookmark 中传递文章 ID,它将从 bookmarks 状态中删除该特定文章。

function Layout() {
  const { response } = useFetch();

  console.log(response);

  const [bookmarks, setBookmarks] = useState([]);

  function handleAddBookMark({title, id}) {
    if (!bookmarks.filter(b => b.id === id).length) {
      setBookmarks([...bookmarks, {title, id}]);
    } else {
      return false;
    }
  }

  function handleRemoveBookmark(id) {
    if (id > -1) {
      setBookmarks(bookmarks => bookmarks.filter(b => b.id !== id));
    }
  }

  if (!response || response.length === 0) {
    return <div> Loading...</div>;
  } else {
    return (
      <div className="Layout__container">
        <div className="Layout__container__mainColumn">
          {response.data.articles.map((article, i) => (
            <Card
              key={i}
              author={article.author}
              title={article.title}
              image={article.urlToImage}
              onClick={() => handleAddBookMark(article)}
              selected={bookmarks.filter(b => b.id === article.id).length ? true : false}
            />
          ))}
        </div>
        <div className="Layout__container__rightColumn">
          <div className="Layout__container__rightColumn__customHr" />
          <div className="Layout__container__rightColumn__bookmarks">
            <span>Your bookmarks</span>
            <p>Articles you bookmark will be added to this list</p>
          </div>
          <BookmarksBar data={bookmarks} onClick={handleRemoveBookmark} />
        </div>
      </div>
    );
  }
}

export default Layout;

【讨论】:

  • 当您点击 handleAddBookMark 时,文章对象的文章标题和 ID 正确插入到书签中?
  • 你能把你的问题添加到codesandbox.io
  • 这里是 Saswata Pal,codesandbox.io/s/snowy-star-f125v?file=/src/components/data.js 当我在沙箱中遇到 CORS 问题时,我更改了来自 useFetch 的数据。现在应用程序中的数据来自一个模拟真实数据结构的假模拟。
  • 我看到你还在传递 article.title 而不是 article 对象,同样在你的模拟数据中 id 丢失了我添加了 id ,现在它正在工作onClick={() =&gt; handleAddBookMark(article)}
  • 在书签栏中还有一个问题,您需要写成 ` `
猜你喜欢
  • 2019-06-12
  • 1970-01-01
  • 2021-09-27
  • 1970-01-01
  • 2016-03-05
  • 2019-12-07
  • 2018-11-20
  • 2013-08-09
  • 1970-01-01
相关资源
最近更新 更多