【问题标题】:How to stop useEffect from loading my modal multiple times?如何阻止 useEffect 多次加载我的模态?
【发布时间】:2021-08-24 02:59:20
【问题描述】:

我有一个基于函数的 React 视图,它有一个基于本地存储中项目的存在加载的模式:

function myView() {
...

        function HelpModal() {

            const [show, setShow] = useState(false);
            
            useEffect(()=>{
              let pop_status = localStorage.getItem('this-page-modal');
              if(!pop_status){
                  setShow(true);
              }
            },[])
            if(!setShow) return null;
            
            
          
            const handleClose = () => {
                localStorage.setItem('this-page-modal', '1');
                setShow(false);
            };
            const handleShow = () => setShow(true);
            
          
            return (
              <>
                <Button variant="primary" onClick={handleShow}>
                 Button text
                </Button>
          
                <Modal show={show} onHide={handleClose}>
                  <Modal.Body>
                      <p>Hey! This is a modal.</p>
                   </Modal.Body>
                  <Modal.Footer>
                    <Button variant="primary" onClick={handleClose}>
                      Close
                    </Button>
                  </Modal.Footer>
                </Modal>
              </>
            );
          }

return (
<div>

  <Container style={{marginTop: "1em"}}>
                <Row>
                    <Col><h1>My View</h1></Col>
                    <Col><span style={{float: "right"}}> <HelpModal /></span></Col>
                </Row>
 </Container>

</div>
);

}

问题:当我加载页面时,模态闪烁并加载了 2 或 3 次。

如何让它只加载一次?任何建议将不胜感激。

【问题讨论】:

  • useEffect 没有多次加载,你使用[] 作为第二个参数,这意味着它只会在构造时被调用,所以有人多次调用你的模态,但你的useEffect 不是问题。

标签: javascript reactjs use-effect


【解决方案1】:

对于一般情况,您可以使用useLayoutEffect 使更新发生得更快,几乎是即时的,而不是在使用useEffect 重新绘制后稍等。

另外,if(!setShow) return null; 行完全是多余的,因为 useState 设置器函数将始终是一个函数,这是真的。

useLayoutEffect(() => {
    const pop_status = localStorage.getItem('this-page-modal');
    if (!pop_status) {
        setShow(true);
    }
}, []);

但是由于效果内部的函数是完全同步的,所以使用存储值作为show状态的初始值会更有意义,而不是调用状态设置器;您可以完全移除效果。

const [show, setShow] = useState(!localStorage.getItem('this-page-modal'));
const handleClose = () => {
    localStorage.setItem('this-page-modal', '1');
    setShow(false);
};
const handleShow = () => setShow(true);
return (
    // ...

【讨论】:

  • 这也不能解决主要问题。
  • 您的问题中没有其他代码可以产生您描述的问题。如果这不能解决问题,则您的问题缺少minimal reproducible example - 请在问题中编辑足够的代码以使问题可重现,最好是在实时堆栈片段中。
【解决方案2】:

您的设置可能会导致基于此处未显示的代码重新渲染,因此很难诊断出确切的问题。要尝试的一件事可能是将console.log 语句放在各种函数范围内,以查看它在加载时被重新渲染了多少次。除此之外,(并同意先前的答案)我认为您可以通过直接来自 localStorage 的条件渲染来简化代码并获得相同的结果。可能是这样的:

function HelpModal() {
  const [show, setShow] = useState(localStorage.getItem("this-page-modal"));

  const handleClose = () => {
    setShow(false);
    localStorage.setItem("this-page-modal", false);
  };

  const handleShow = () => {
    setShow(true);
    localStorage.setItem("this-page-modal", true);
  };

  return (
    <>
      <Button variant="primary" onClick={handleShow}>
        Button text
      </Button>

      <Modal show={show} onHide={handleClose}>
        <Modal.Body>
          <p>Hey! This is a modal.</p>
        </Modal.Body>
        <Modal.Footer>
          <Button variant="primary" onClick={handleClose}>
            Close
          </Button>
        </Modal.Footer>
      </Modal>
    </>
  );
}

function myView() {
  return (
    <>
      <HelpModal />
    </>
  );
}

【讨论】:

    猜你喜欢
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    相关资源
    最近更新 更多