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

React扫码触发的模态框点击关闭后立即复现问题求助

问题根源

  1. 父子组件的useEffect均未声明依赖数组,每次组件重渲染都会重复执行内部逻辑
  2. 扫码后父组件的flag状态始终为true,子组件每次重渲染都会触发useEffect将内部open重置为true,导致关闭后立刻重新弹出
  3. 子组件关闭事件仅修改了内部状态,未同步修改父组件的控制状态,父子状态不同步
  4. 父组件扫码后data值未清空,会重复触发接口请求逻辑

修复方案

1. 修改父组件 QrScanner

  • 给useEffect添加[data]依赖,避免重复执行请求逻辑
  • 新增关闭模态框的回调方法,同步重置flag和data状态
  • 将关闭回调作为prop传给子组件

修改后代码:

const QrScanner = () => {
  const [data, setData ] = useState('');
  const [flag, setFlag] = useState(false);
  const [title, setTitle] = useState('');

  const history = useHistory();

  // 新增关闭模态框方法
  const handleCloseModal = () => {
    setFlag(false);
    setData(''); // 清空扫描数据,避免重复触发请求
  };

  // 添加依赖数组 [data],仅data变化时执行
  useEffect(() => {
    if(data === '') {
      return;
    }
    if (Number.isInteger(parseInt(data))) { 
      axios.get('/api/qrcodescanner/ean/' + data)
        .then(res => {
          if (res.data.title != false) {
            setFlag(true);
            setTitle(res.data.title);
          } else {
            setData('Sorry, Wrong barcode!');
          }
        })
    }
  }, [data])

  return (
    <>
      <BarcodeScannerComponent
        width={500}
        height={500}
        onUpdate={(err, result) => {
          if (result) {
            setData(result.text);
          }
        }}
      />
      <p className="modal-result-show">{data}</p>
      {/* 传入关闭回调 */}
      <ResponseModal flag={flag} data={data} title={title} onClose={handleCloseModal}/>    
    </>
  );
}

2. 修改子组件 ResponseModal

推荐直接用父组件传入的flag控制模态框显示,不需要额外维护内部open状态,避免状态重复,修改后代码:

const ResponseModal = (props) => {
  const closeIcon = (
    <svg fill="black" width="28" height="28" viewBox="0 0 36 36" data-testid="close-icon"><path d="M28.5 9.62L26.38 7.5 18 15.88 9.62 7.5 7.5 9.62 15.88 18 7.5 26.38l2.12 2.12L18 20.12l8.38 8.38 2.12-2.12L20.12 18z"></path></svg>
  );

  const {flag, title, onClose} = props;

  return (
    <>
      <Modal open={flag} onClose={onClose} center closeIcon={closeIcon} modalId="response-modal">
        <div className="qr-modal-header-stock">
          <h5>Enter stock</h5>
          <p>{title}</p>
        </div>
      </Modal>
    </ >
  );
}

如果你需要保留子组件内部的open状态做额外控制,修改如下:

const ResponseModal = (props) => {
  const closeIcon = (
    <svg fill="black" width="28" height="28" viewBox="0 0 36 36" data-testid="close-icon"><path d="M28.5 9.62L26.38 7.5 18 15.88 9.62 7.5 7.5 9.62 15.88 18 7.5 26.38l2.12 2.12L18 20.12l8.38 8.38 2.12-2.12L20.12 18z"></path></svg>
  );

  const {flag, title, onClose} = props;
  const [open, setOpen] = useState(false);

  const onCloseModal = () => {
    setOpen(false);
    onClose(); // 调用父组件关闭回调
  };
  
  // 添加依赖数组 [flag],仅flag变化时执行
  useEffect(() => {
    if(flag) {
      setOpen(true);
    }
  }, [flag])

  return (
    <>
      <Modal open={open} onClose={onCloseModal} center closeIcon={closeIcon} modalId="response-modal">
        <div className="qr-modal-header-stock">
          <h5>Enter stock</h5>
          <p>{title}</p>
        </div>
      </Modal>
    </ >
  );
}

内容的提问来源于stack exchange,提问作者Áron Pop Adorján

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:36:01