首页 > 解决方案 > 如何制作为每个按钮图打开 onClick 的模态图?

问题描述

我目前有一个功能组件,如下所示,我从useValues()钩子中生成了几个按钮。

const ButtonsWithModals = () => {
  const [objects, loading] = useObjects() // `loading` is used in my `App` HOC
  const [isModalOpen, setModalOpen] = React.useState()
  const [modal, setModal] = React.useState([])
  
  const ref = React.useRef()
  
  function onClickOutside() {
    setModalOpen(false)
  }
  
  useClickOutside(ref, onClickOutside)
  
  return (
    <>
      {isModalOpen ? (
        <RenderModal ref={ref} key={modal} objectValue3={object.value3} />
        ) : (
        objects.map((object, index) => (
          <button
            style={{size: "" + object.value3}} 
            onClick={() => setModalOpen(true) setModal(index)}
          >
            <p>{object.value2}</p>
          </button>
        ))
        )
      }
    </>
  )
}

useVObjects()钩子获取并返回我渲染为按钮的对象列表values.map((object, index) {...})

当我尝试呈现用户单击的特定按钮独有的模式时,我的挣扎就出现了。

这是我的<RenderModal/>组件逻辑的样子:

const RenderModal = ({ref, key, objectValue}) => {
  
  return (
    <>
      <div class="modal">
        <div ref={ref} key={key}>
          <p>{objectValue}</p>
        </div>
      </div>
    </>
  )
}

当模式打开时,我希望我的RenderModal组件根据单击的按钮显示对象的信息,因此如下所示:

{isModalOpen ? (
        <RenderModal ref={ref} key={modal} objectValue3={objects.value3} />
        ...

位置objectValue3objects.value3根据用户单击的按钮进行更改。我尝试了很多不同的东西,并且一直在引用这 4 个 StackOverflow 帖子,但它们使用类,我不确定如何使用钩子复制所需的效果:

标签: reactjsmodal-dialogreact-hooksarray.prototype.map

解决方案


我最终做的是一件又快又脏的事情。在查看 Robin Wieruch关于 React CSS的教程后,我相信有一种更优化的方法可以实现我想要实现的目标。

这是我的主要CardsAndModals功能组件逻辑与钩子:

const CardsAndModals = () => {
  const [objects] = useObjects()

  const [isModalOpen, setModalOpen] = React.useState(false)
  const [modal, setModal] = React.useState(null)
  
  /* Lists of property values for each object */
  let objectValues1 = objects.map(object => object.value1)
  let objectValues2 = objects.map(object => object.value2)
  let objectValues3 = objects.map(object => object.value3)
  let objectValues4 = objects.map(object => object.value4)
  
  // used when calling `useClickOutside()` hook
  const ref = React.useRef()  
  
  function onClickOutside() {
    setModalOpen(false)
  }
  
  function handleOnClick(index) {
    setModalOpen(true)
    setModal(index)
  }
 
  useClickOutside(ref, onClickOutside)
  
  return (
    <>
      {objects.map((object, index) => (
        <button
          class="card" 
          style={{size: "" + object.value3}} 
          onClick={() => handleOnClick(index)}
        >
          <p>{object.value1}</p>
          <p class="helper-text">Click for more info!</p>
        </button>
      ))
      }
      {isModalOpen && setModal != null ? (
        <RenderModal 
          ref={ref} 
          key={modal} 
          objectValue1={objectValues1[modal]}
          objectValue2={objectValues2[modal]}
          objectValue3={objectValues3[modal]}
          objectValue4={objectValues4[modal]}
        />
      ) : (
        ""  
      )}
    </>
  )
}

最后,这是我重构的RenderModals功能组件(假设objectValue1=== 名称):

const RenderModal = ({ref, key, objectName, objectValue2, objectValue3, objectValue4, objectParagraph}) => {
  return (
    <>
      <div class="modal-backdrop">
          <div class="modal-content" ref={ref} key={key}>
            <h1 class="object-info-header">
              {objectName}
            </h1>
            <p class="object-info-value2">
              value2: {objectValue2}
            </p>
            <p class="object-info-value3">
              value3: {objectValue3}
            </p>
            <p class="object-info-value4">
              value4: {objectValue4}
            </p><br />
            <div class="object-info-paragraph">
              <p>
                Here could hold more info about the object 
                <strong>{" " + objectName}</strong>,
                pulled from another API (e.g., Wikipedia):
              </p><br />
              <p>Did you know?</p>
              <p>
                <em>
                  Lorem ipsum dolor sit amet, consectetur adipiscing
                  elit. Curabitur in viverra turpis. Vivamus id
                  pretium sapien, eu rhoncus ligula. Nam magna ante,
                  viverra ac neque at, volutpat finibus arcu. 
                  Pellentesque at rutrum lacus. Vivamus efficitur, 
                  urna quis pulvinar vehicula, ligula justo mollis 
                  dolor, vitae lacinia lectus erat at purus. Duis 
                  ac tortor nunc. Etiam nulla lacus, posuere sit 
                  amet lectus eu, pellentesque iaculis ipsum. 
                  Curabitur vel velit commodo, vestibulum mi a,
                  imperdiet dui.
                </em>
              </p>
            </div>
          </div>
      </div>
    </>
  )
}

分享这个是因为我希望我有这么详细的东西。希望这对你们中的一些人有所帮助!


推荐阅读