You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React状态作为Props传递错误致多模态框弹出问题及优化咨询

问题分析与解决方案

问题根源

你在父组件CustomButton中使用了单一的布尔值状态clicked,所有子Button组件共享这个状态。当任意按钮触发setClicked(true)时,所有Button组件都会检测到clicked为true,导致三个Modal同时渲染,这就是所有弹窗一起弹出的核心原因。

解决方案

提供两种可行方案,可根据需求选择:

方案1:父组件维护当前激活的弹窗标识(适合统一控制弹窗)

这种方式确保同一时间只有一个弹窗打开,父组件通过记录当前激活的按钮名称来精准控制弹窗显示:

父组件 CustomButton.jsx

import React, { useState } from 'react'
import Button from '../components/Button'

function CustomButton() {
  // 用null表示无弹窗,用按钮名称标记当前激活的弹窗
  const [activeModal, setActiveModal] = useState(null)

  return (
    <div className='CustomButton'>
      <Navbar />
      <Button 
        activeModal={activeModal}
        setActiveModal={setActiveModal} 
        name="Button One" 
      />
      <Button 
        activeModal={activeModal}
        setActiveModal={setActiveModal} 
        name="Button Two" 
      />
      <Button 
        activeModal={activeModal}
        setActiveModal={setActiveModal} 
        name="Button Three" 
      />
    </div>
  )
}

export default CustomButton

子组件 Button.jsx

这里用你想要的if判断写法控制Modal渲染,逻辑更直观:

import React from 'react'
import Modal from './Modal/Modal'

function Button({ setActiveModal, name, activeModal }) {
  // 单独提取Modal渲染逻辑
  const renderModal = () => {
    if (activeModal === name) {
      return <Modal 
        closeModal={() => setActiveModal(null)} 
        name={`You Clicked ${name}`} 
      />
    }
    return null
  }

  return (
    <div>
      <button onClick={() => setActiveModal(name)}>{name}</button>
      {renderModal()}
    </div>
  )
}

export default Button

Modal组件 Modal.jsx(简化点击逻辑)

import React from 'react'

function Modal({ closeModal, name }) {
  return (
    <div className='modal'>
      <div className='modalContainer'>
        <p>{name}</p>
        <div>
          <button onClick={closeModal}>&times;</button>
        </div> 
      </div>
    </div>
  )
}

export default Modal

方案2:每个Button组件独立维护状态(适合完全独立的按钮)

把弹窗状态下放到每个Button组件内部,让每个按钮自己控制弹窗的显示/隐藏,互不干扰:

父组件 CustomButton.jsx(无需维护状态)

import React from 'react'
import Button from '../components/Button'

function CustomButton() {
  return (
    <div className='CustomButton'>
      <Navbar />
      <Button name="Button One" />
      <Button name="Button Two" />
      <Button name="Button Three" />
    </div>
  )
}

export default CustomButton

子组件 Button.jsx

import React, { useState } from 'react'
import Modal from './Modal/Modal'

function Button({ name }) {
  const [clicked, setClicked] = useState(false)

  const renderModal = () => {
    if (clicked) {
      return <Modal 
        closeModal={() => setClicked(false)} 
        name={`You Clicked ${name}`} 
      />
    }
    return null
  }

  return (
    <div>
      <button onClick={() => setClicked(true)}>{name}</button>
      {renderModal()}
    </div>
  )
}

export default Button

关于if写法的补充说明

除了提取函数的方式,也可以在JSX中用立即执行函数实现类似逻辑,但可读性不如提取函数:

{(() => {
  if (clicked) {
    return <Modal closeModal={() => setClicked(false)} name={`You Clicked ${name}`} />
  }
})()}

推荐使用提取函数的方式,代码结构更清晰,便于后续维护。

内容的提问来源于stack exchange,提问作者अंशुल

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:24:19