reactjs - 弹出窗口:显示弹出窗口而不单击按钮

reactjs - Popup : Showing a popup withouth clicking a button

我想显示一个带有以下代码的弹出窗口:

const [showPopup, setShowPopup] = useState(false);

我用这种方式处理 show/setpopup :

 <Popup open={showPopup} onClose={() => setShowPopup(false)} modal>
    <span> Popup content </span>
  </Popup>


  {meta.error === 'codigo 2 fatores incorreto' ? (
    setShowPopup(true)
  ) : (
    <Popup style={{ visibility: "hidden" }}>.</Popup>
  )}

当它在 case (meta.error === 'codigo 2 fatores incorreto') 中掉落时,他掉进了一个循环并出现以下错误:(重新渲染太多。React 将渲染次数限制为防止死循环。),有人知道怎么解决吗?
我使用了这个文档 https://react-popup.elazizi.com/component-api/

整个组件[工作]:

import React, { useState, useEffect } from 'react';
import { ErrorMessage, useField } from "formik";
import { StyledTextInput, StyledLabel, StyledIcon, ErrorMsg } from "./Styles";

// Eye for password
import { FiEyeOff, FiEye } from "react-icons/fi";

//pop up style.css 
import '../assets/css/popup.css'
// Import popup lib
import Popup from "reactjs-popup";
import 'reactjs-popup/dist/index.css';


function MyComponent() { 
  const [state, setState] = useState();
  setState(true);
  return (
    <Popup model
    trigger={open => <MyComponent open={open} />}
    position="right center"
    closeOnDocumentClick
  >
    <span> Popup content </span>  </Popup>
  );
}



export const TextInput = ({ icon, ...props }) => {
  const [field, meta] = useField(props);
  const [showpass, setShowpass] = useState(false);
  const [showPopup, setShowPopup] = useState(false);


  useEffect(() => {
    if(meta.error === 'codigo 2 fatores incorreto'){
    setShowPopup(true);
    }
  }, [meta.error])
  

  return (
    <div style={{ position: "relative" }}>
      <StyledLabel htmlFor={props.name}>{props.label}</StyledLabel>
      {props.type !== "password" && (
        <StyledTextInput
          invalid={meta.touched && meta.error}
          {...field}
          {...props}
        />
      )}
      {props.type === "password" && (
        <StyledTextInput
          invalid={meta.touched && meta.error}
          {...field}
          {...props}
          type={showpass ? "text" : "password"}
        />
      )}
      <StyledIcon>{icon}</StyledIcon>
      {props.type === "password" && (
        <StyledIcon onClick={() => setShowpass(!showpass)} right>
          {showpass && <FiEye />}
          {!showpass && <FiEyeOff />}
        </StyledIcon>
      )}
      {meta.touched && meta.error ? (
        <ErrorMsg>{meta.error}</ErrorMsg>
      ) : (
        <ErrorMsg style={{ visibility: "hidden" }}>.</ErrorMsg>
      )}

      <Popup open={showPopup} onClose={() => setShowPopup(false)} modal>
      {close => (
      <div className="modal">
        <button className="close" onClick={close}>
          &times;
        </button>

        
             
      </div>
    )}
    
  </Popup>
    {meta.error === "codigo 2 fatores incorreto" ? (
      !showPopup ? ( setShowPopup(true)) : ("") // <-- Only set state if not true 
 ) : <Popup>.</Popup>}
    </div>
  );
};

如果我没看错的话,似乎只要 meta.error 与您的字符串匹配,它就会不断调用 setShowPopup(true) 因为状态已更新 - 调用该函数会导致重新渲染,在此期间我假设 meta.error 仍然是 'codigo 2 fatores incorreto'.

我相信你可以做类似下面的事情来停止重新渲染。

{meta.error === "codigo 2 fatores incorreto" ? (
    !showPopup ? setShowPopup(true) : "" // <-- Only set state if not true
) : (
    <Popup style={{visibility: "hidden"}}>.</Popup>
)}

虽然我可能错了,我可能误解了片段。

我们应该永远在组件渲染方法中使用setState。对于 class 组件,它位于 render() 内部,对于功能组件,它位于 return() 内部或组件主体中的任何位置,如下所示:

function MyComponent() { 
   const [state, setState] = useState();
   setState(true);
   return (...);
}

这将始终导致无限循环。

  1. setState() 触发重新渲染。
  2. 重新渲染再次运行组件代码并触发setState()。回到 1.

React 提供了一些工具来处理你的情况,例如 useEffect.

而不是

{meta.error === "codigo 2 fatores incorreto" ? (
        setShowPopup(true)
      ) : (
        <Popup style={{ visibility: "hidden" }}></Popup>
      )}

你应该

export const TextInput = ({ icon, ...props }) => {
  ...
  useEffect(() => {
    if(meta.error){
      setShowPopup(true);
    }
  }, [meta.error])
  
  return (
    ...
    <Popup style={{visibility: "hidden"}}>.</Popup>
  );