首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按钮使用布尔状态钩子进行两次单击。

按钮使用布尔状态钩子进行两次单击。
EN

Stack Overflow用户
提问于 2022-11-16 16:22:04
回答 2查看 45关注 0票数 0

我对此反应很新。在这里,我为一个项目做了一个小的表单组件(包括一些顺风)。表单的上方是一个隐藏的警告框,它将显示提交(绿色表示成功,红色表示失败)。我附加到表单上的处理程序显示了正确的警报,但是它需要两次单击。在处理程序validateFormData()中,我正在重置状态(isError)。我知道useState钩子是异步的,所以我的isError变量在呈现警告框之前没有正确更新(对吗?)我尝试过将回调传递给我的setIsError函数(在在线查找解决方案之后),但我无法解决这个问题。我在这里的球场对不对?还是我漏掉了什么?

代码语言:javascript
复制
function ContactInsert() {
    const contactForm = useRef(null);
    const alertBox = useRef(null);
    const [isError, setIsError] = useState(false);

    function showAlertBox() {
        alertBox.current.classList.add("alert-show");
        setTimeout(() => {
            alertBox.current.classList.remove("alert-show");
        }, 3000);
    }

    async function validateFormData() {
        // unpack and validate data
        const name = contactForm.current.querySelector("[name=name]").value.trim();
        const email = contactForm.current.querySelector("[name=email]").value.trim();
        const comment = contactForm.current.querySelector("[name=comment]").value.trim();

        if (name.length > 0 && email.length > 0 && comment.length > 0) {
            setIsError(false);
        } else {
            setIsError(true);
        }
        showAlertBox();
    }


    return (
        <div className="flex flex-col">
            <div className="flex justify-center my-2">
                <h1>Drop me a message!</h1>
            </div>
            {isError ?
                <div ref={alertBox} className="flex h-12 w-2/3 justify-center bg-[#ff462e] invisible">hello</div> :
                <div ref={alertBox} className="flex h-12 w-2/3 justify-center bg-[#77ff6e] invisible">hello</div>
            }
            <form 
            className="flex flex-col items-center justify-center md:h-full" 
            method="POST"
            name="contact"
            id="contact"
            type="submit"
            ref={contactForm}
            onSubmit={(e) => {
                e.preventDefault();
                validateFormData();
            }}
            >
                <div className="flex flex-col justify-between w-2/3">
                    <label>name</label>
                    <input type="text" name="name"/>
                </div>
                <br/>
                <div className="flex flex-col justify-between w-2/3">
                    <label>email</label>
                    <input type="text" name="email"/>
                </div>
                <br/>
                <div className="flex flex-col justify-between w-2/3 h-40">
                    <label>comment</label>
                    <textarea className="h-full" name="comment"/>
                </div>
                <div className="flex w-2/3 justify-start my-4">
                    <button className="p-1" form="contact">Submit</button>
                </div>
            </form>
        </div>
    );
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-16 17:10:19

直接操作DOM总是一个坏主意,因为react将很难与呈现的输出匹配,并且违背了使用React的目的。最好是将这些信息存储在状态中,然后让react来处理它。

此外,setState是异步的,这将迫使react组件重定向。我们可以使用useEffect让React知道组件必须在下一次呈现时做一些事情。

代码语言:javascript
复制
function ContactInsert() {
  const [isError, setIsError] = useState(false);
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [comment, setComment] = useState('');
  const [displayAlert, setDisplayAlert] = useState(false); 
  
  const handleNameOnchangeHandler = (event) => {
      setName(event.target.value);
  };
  
  const handleEmailOnchangeHandler = (event) => {
      setName(event.target.value);
  };
  
  const handleCommentOnchangeHandler = (event) => {
      setName(event.target.value);
  };

  const validateFormData = () => {
    const hasError = !name || !email || !comment;
  
    setIsError(hasError);
  }
  
  useEffect(() => {
    if(isError) {
        setDisplayAlert(true);
      
      setTimeout(() => {
        setDisplayAlert(false);
        setIsError(false);
      }, 3000);
    }
  }, [isError]);


  return (
        <div className="flex flex-col">
            <div className="flex justify-center my-2">
                <h1>Drop me a message!</h1>
            </div>
            {displayAlert ?
                <div ref={alertBox} className="flex h-12 w-2/3 justify-center bg-[#ff462e] show-alert">hello</div> : null
                
            }
            <form 
              className="flex flex-col items-center justify-center md:h-full" 
              method="POST"
              name="contact"
              id="contact"
              type="submit"
              ref={contactForm}
              onSubmit={(e) => {
                  e.preventDefault();
                  validateFormData();
              }}
            >
                <div className="flex flex-col justify-between w-2/3">
                    <label>name</label>
                    <input type="text" name="name" onchange={handleNameOnchangeHandler}/>
                </div>
                <br/>
                <div className="flex flex-col justify-between w-2/3">
                    <label>email</label>
                    <input type="text" name="email" onchange={handleEmailOnchangeHandler}/>
                </div>
                <br/>
                <div className="flex flex-col justify-between w-2/3 h-40">
                    <label>comment</label>
                    <textarea className="h-full" name="comment" onchange={handleCommentOnchangeHandler}/>
                </div>
                <div className="flex w-2/3 justify-start my-4">
                    <button className="p-1" form="contact">Submit</button>
                </div>
            </form>
        </div>
    );
}

这是一个使用useEffect的示例。不使用它也可以做到这一点。您还可以使用单个onchange处理程序,并根据触发事件的目标设置值。

票数 1
EN

Stack Overflow用户

发布于 2022-11-16 17:05:29

你的反应是完全错误的。我强烈建议您仔细阅读react并深入了解呈现概念。我在您的代码中看到的问题是:

  1. 获取输入值的方式不是很好。您应该定义一个状态(受控组件)或传递一个引用来获得值(uncontrolled).

使用ref更改css类的

  1. 将无法工作,因为它不会触发应用程序中的重命名器(详细信息请参阅useRef文档)您应该定义一个新的状态并使用该状态来更改您的className.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74463918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档