【问题标题】:How to Create Show/Hide button when Looping in React在 React 中循环时如何创建显示/隐藏按钮
【发布时间】:2022-01-22 18:10:09
【问题描述】:

我正在开发一个网站,但遇到了问题。问题是我正在循环数据文件以创建一些项目卡。每个项目卡都有一个显示更多/显示更少按钮来显示/隐藏卡描述。

我的问题是当前设置正在映射数据并导致它,因此每当单击一个时,所有三个都同时打开或关闭。请帮我解决这个问题。相关代码如下:

数据示例:

{
name: "Hot in the Biscuit",
id: "3a34",
image: "/images/bonnie.jpg",
description: "A multi-page front-end business website for a local restaurant in Koh Samui, Thailand. Custom design built with vanilla JavaScript, HTML and CSS.",
link: "https://www.xxxxxxxxxxxxx.com",
date: "2021",
github: "https://github.com/xxxxxxxxxxxxxxxxxxxxxx"
},

展示展示组件的英雄文件:

               <h1>Featured Projects</h1>
             <div>
             <Showcase/>
             </div>

展示卡片的创建位置(删除了不必要的代码 - 类和图像):

const Showcase = () => {
    const {readMore, setReadMore} = useContext(HeroContext)
    const {toggleMenu} = useContext(NavbarContext)
    return(
        <>
  {showcase.map((item) => {
    const {id, name, image, link, github, description, date} = item;
      return (
        <div key={id}>
        <div>
       {!toggleMenu &&
        <div>
        <Image/>
        </div>
       }
        </div>
        <div>
            <div>
                <h2>{name} | {date}</h2>
            </div>
            <div>
                <h4>{ readMore[id] ?   <-- THIS IS WHERE YOU NEED AN ID
                    description :
                    `${description.substring(0, 100)}...`
                    } <button key={id} onClick={() => setReadMore(!readMore)}>{readMore[id] ? "Show Less" : "Show More"}</button>
                    </h4>
            </div>
            <div>
            <a href={github}>
                <FiGithub/>
            </a>
                <a href={link}>
                <h4 >See For Yourself! &#8594;</h4>
                </a>
            </div>
        </div>
    </div>
      )
  })}   
  </>
    )   
}
export default Showcase
           

所以我只需要一些帮助来弄清楚如何设置它,以便每个按钮都知道正在点击哪张卡片并且只打开那个按钮。非常感谢你帮助我。非常感谢您的宝贵时间和帮助。

博迪

【问题讨论】:

    标签: reactjs loops react-hooks next.js uibutton


    【解决方案1】:

    如果将展示项目拆分为新组件会更容易。

    const ShowCaseItem = ({ data }) => {
      const { toggleMenu } = useContext(NavbarContext)
      const [readMore, setReadMore] = useState(false)
      const { id, name, image, link, github, description, date } = data;
      return (
        <div key={id}>
          <div>
            {!toggleMenu &&
              <div>
                <Image />
              </div>
            }
          </div>
          <div>
            <div>
              <h2>{name} | {date}</h2>
            </div>
            <div>
              <h4>{readMore ?
                description :
                `${description.substring(0, 100)}...`
              } <button key={id} onClick={() => setReadMore(!readMore)}>{readMore ? "Show Less" : "Show More"}</button>
              </h4>
            </div>
            <div>
              <a href={github}>
                <FiGithub />
              </a>
              <a href={link}>
                <h4 >See For Yourself! &#8594;</h4>
              </a>
            </div>
          </div>
        </div>
      )
    }
    const Showcase = () => {
      const { readMore, setReadMore } = useContext(HeroContext)
      return (
        <>
          {showcase.map((item) => <ShowCaseItem data={item} />)}
        </>
      )
    }
    export default Showcase
    

    【讨论】:

      【解决方案2】:

      您应该更新HeroContext 状态以保存对显示/隐藏的ids 的引用。

      例子:

      const [readMore, setReadMore] = useState({});
      
      const readMoreToggler = (id) => setReadMore(state => ({
        ...state,
        [id]: !state[id], // <-- toggle boolean value
      }));
      
      // context value
      {
        readmore,
        setReadMore: readMoreToggler, // pass readMoreToggler as setReadMore
      } 
      

      ...

      const { readMore, setReadMore } = useContext(HeroContext);
      
      ...
      
      {showcase.map((item) => {
        const {id, name, image, link, github, description, date} = item;
        return (
          <div key={id}>
            <div>
              ...
            </div>
            <div>
              ...
              <div>
                <h4>
                  {readMore[id] // <-- check by id if toggled true|false
                    ? description
                    : `${description.substring(0, 100)}...`
                  }
                  <button
                    onClick={() => setReadMore(id)} // <-- pass id to toggle
                  >
                    {readMore[id] ? "Show Less" : "Show More"} // <-- check by id if toggled true|false
                  </button>
                </h4>
              </div>
            <div>
            ...
          </div>
        )
      })}  
      

      【讨论】:

      • 您好 Drew,我非常感谢您的慷慨帮助和提供的时间。没想到这么快就收到了答复。我期待着有一天能像你一样乐于助人,我希望早晚。再次感谢您。
      • 嗨 Drew - 很抱歉打扰您,但请您澄清一下我是否应该保留原来的 useState: const {readMore, setReadMore} = useContext(HeroContext) 然后将您的建议添加为第二个状态拿着一个空的物体?您的命名在我的和您的之间切换,但随后您将函数命名为 readMore,现在我很困惑,因为那是我原来的 useState 值的名称,但随后您也导入了 setReadMore。当我删除我的 readMore/setReadMore 并尝试仅使用您的设置时,我没有成功。任何额外的澄清将不胜感激。再次道歉。
      • @BodiAugustus 不用担心。抱歉,如果更改有点令人困惑。我这样做是因为您实际上只想公开 readmore 状态(现在是一个带有 id 键的对象)和一个 setReadMore 函数来更新状态。不同之处在于保持上下文 API 几乎相同,即状态和更新函数,但现在提供者保持对状态如何更新的控制。您可以轻松地保留您的命名,调用其他处理函数并提供 that 而不是您的 setReadMore 状态更新程序。这有意义吗?
      • 很抱歉 Drew,我说得太早了 - 我想精简一下,我是否正确地假设 setReadMore 真的应该是 setReadMoreState?如果不是这样,您能否告诉我 setReadMore 应该来自哪里?从我的州?我应该为此有两种状态,一个假对象和一个空对象,还是只是您的示例中显示的空对象状态?抱歉所有问题..
      • 言语无法表达我对您的耐心、时间和帮助 Drew 的感谢。非常感谢。对于将来遇到此类似问题的任何人,一旦您拥有 ID,您还需要将其应用于描述 - 检查我最初发布的编辑,仅添加 ID 以向您展示我的意思。再次感谢德鲁。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-09
      • 2011-06-30
      • 1970-01-01
      • 2021-06-05
      • 1970-01-01
      相关资源
      最近更新 更多