【问题标题】:how do i focus an input in react form for form validation我如何将输入集中在反应表单中以进行表单验证
【发布时间】:2021-03-09 08:01:39
【问题描述】:

所以我专门为这个问题编写了这个反应小反应形式,我想给它添加一个功能。

代码如下:

import React, { useState } from "react";

export default function App() {
  const [formInfo, setFormInfo] = useState({ name: "", email: "" });

  function onch(e) {
    const { value, id } = e.target;

    id === "name"
      ? setFormInfo({ ...formInfo, name: value })
      : setFormInfo({ ...setFormInfo, email: value });
  }

  function onsub(e) {
    e.preventDefault();

    const { name, email } = formInfo;

    if (name === "") {
      alert("fill your name");
    } else if (email === "") {
      alert("fill out your email");
    } else {
      alert("done");
      setFormInfo({ name: "", email: "" });
    }
  }

  const { name, email } = formInfo;

  return (
    <form action="" onSubmit={onsub}>
      <div className="input">
        <label htmlFor="">Name</label>
        <input type="text" name="" id="name" onChange={onch} value={name} />
      </div>
      <div className="input">
        <label htmlFor="">E-mail</label>
        <input type="text" name="" id="email" onChange={onch} value={email} />
      </div>

      <div className="input">
        <button type="submit">Submit</button>
      </div>
    </form>
  );
}

您会看到如果您没有填写其中一个输入,它将触发警报。但我想用焦点替换警报。因此,当我忘记填写某个输入时,它将专注于那个空输入 基本上是告诉我填写。

提前致谢

【问题讨论】:

  • 您是否考虑将required 添加到input 中?如果用户不填写,它将聚焦并警告用户

标签: javascript reactjs react-forms


【解决方案1】:

您可以使用useRef 钩子来实现这一点,代码将焦点放在第一个空元素上并使其边框变为红色

 import React, { useState, useRef } from "react";

 export default function App() {
 const [formInfo, setFormInfo] = useState({ name: "", email: "" });

function onch(e) {
const { value, id } = e.target;

id === "name"
  ? setFormInfo({ ...formInfo, name: value })
  : setFormInfo({ ...setFormInfo, email: value });
}

const nameRef = useRef();
const emailRef = useRef();

function onsub(e) {
e.preventDefault();

const { name, email } = formInfo;

if (name === "") {
  nameRef.current.focus();
  nameRef.current.style.border = "1px solid red";
} else if (email === "") {
  nameRef.current.focus();
  nameRef.current.style.border = "1px solid red";
} else {
  alert("done");
  setFormInfo({ name: "", email: "" });
}
}

const { name, email } = formInfo;

return (
<form action="" onSubmit={onsub}>
  <div className="input">
    <label htmlFor="">Name</label>
    <input
      ref={nameRef}
      type="text"
      name=""
      id="name"
      onChange={onch}
      value={name}
    />
  </div>
  <div className="input">
    <label htmlFor="">E-mail</label>
    <input
      ref={emailRef}
      type="text"
      name=""
      id="email"
      onChange={onch}
      value={email}
    />
  </div>

  <div className="input">
    <button type="submit">Submit</button>
  </div>
</form>
);
}

【讨论】:

    【解决方案2】:

    您应该使用ref 来访问一个元素,然后为它触发focus()。有useRef 钩子可以做到这一点。 您的代码将是:

    import React, { useState, useRef } from "react";
    
    export default function App() {
      const [formInfo, setFormInfo] = useState({ name: "", email: "" });
      const nameRef = useRef();
      const emailRef = useRef();
    
      function onch(e) {
        const { value, id } = e.target;
    
        id === "name"
          ? setFormInfo({ ...formInfo, name: value })
          : setFormInfo({ ...setFormInfo, email: value });
      }
    
      function onsub(e) {
        e.preventDefault();
    
        const { name, email } = formInfo;
    
        if (name === "") {
          nameRef.current.focus();
        } else if (email === "") {
          emailRef.current.focus();
        } else {
          alert("done");
          setFormInfo({ name: "", email: "" });
        }
      }
    
      const { name, email } = formInfo;
    
      return (
        <form action="" onSubmit={onsub}>
          <div className="input">
            <label htmlFor="">Name</label>
            <input
              type="text"
              name=""
              id="name"
              onChange={onch}
              value={name}
              ref={nameRef}
            />
          </div>
          <div className="input">
            <label htmlFor="">E-mail</label>
            <input
              type="text"
              name=""
              id="email"
              onChange={onch}
              value={email}
              ref={emailRef}
            />
          </div>
    
          <div className="input">
            <button type="submit">Submit</button>
          </div>
        </form>
      );
    }
    

    要了解有关ref 的更多信息,请阅读documentation

    【讨论】:

      【解决方案3】:

      您可以使用 react 的 createRef() api 创建类似的东西。

      class MyComponent extends React.Component {
      constructor(props) {
      super(props);
      
      this.inputRef = React.createRef();
      }
      
      render() {
      return <input type="text" ref={this.inputRef} />;
      }
      
      componentDidMount() {
      this.inputRef.current.focus();
      }
      }
      

      此示例取自 react.org

      【讨论】:

        【解决方案4】:

        更新

        经过深思熟虑,我想展示如何在反应中正确使用querySelector,并在过程中简化示例:

        import React, { useCallback, useRef } from "react";
        
        export default function App() {
          const formRef = useRef(null);
        
          const handleSubmit = useCallback((e) => {
            e.preventDefault();
        
            const formData = new FormData(e.target);
        
            for (let [name, value] of formData.entries()) {
              if (!value) {
                formRef.current.querySelector(`input[name=${name}]`).focus()
                break
              }
            }
            // do something with the formData
          }, []);
        
          return (
            <form ref={formRef} action="" onSubmit={handleSubmit}>
              <div className="input">
                <label htmlFor="">Name</label>
                <input type="text" name="name" id="name" />
              </div>
              <div className="input">
                <label htmlFor="">E-mail</label>
                <input type="text" name="email" id="email" />
              </div>
        
              <div className="input">
                <button type="submit">Submit</button>
              </div>
            </form>
          );
        }
        
        

        您可以访问事件中的目标(表单),然后在其中查询以到达您正在寻找的元素,并将它们聚焦。在这种情况下不需要反应参考。请注意,通常不建议直接查询 DOM。文档确实将管理焦点指定为 refs 的预期用途,如 here

        import React, { useState } from "react";
        import "./styles.css";
        
        export default function App() {
        
          const [formInfo, setFormInfo] = useState({name: '', email: ''})
        
        
          function onch(e){
            const {value, id} = e.target
        
            id === 'name' ? setFormInfo({...formInfo, name: value}) : setFormInfo({...setFormInfo, email: value})
        
          }
        
          function onsub(e){
            e.preventDefault()
        
            const {name, email} = formInfo
            
            if(name === ''){
              e.target.querySelector('#name').focus()
            }
            else if(email === ''){
              e.target.querySelector('#email').focus()
            }else{
              alert('done')
              setFormInfo({name: '', email: ''})
            }
            
          }
        
          const {name, email} = formInfo
        
          return (
          <form action="" onSubmit={onsub}>
        
            <div className="input">
              <label htmlFor="">Name</label>
              <input type="text" name="" id="name" onChange={onch} value={name}/>
            </div>
            <div className="input">
              <label htmlFor="">E-mail</label>
              <input type="text" name="" id="email" onChange={onch} value={email}/>
            </div>
           
            <div className="input">
              <button type="submit">Submit</button>
            </div>
        
          </form>
          );
        }
        
        
        

        【讨论】:

        • 你不应该使用 querySelector 来访问组件,因为 React 使用 Virtual DOM 而querySelector 可以访问读取 DOM
        • 嗯,是的,我还假设您还应该访问 currentTarget 而不是 target。但是如果我有一个包含 30 个字段的表单,我不想添加 30 个引用。此外,为了获得焦点,无论如何您都需要实际的 DOM,这是一个非可变操作。很安全
        • 获取真正的 DOM 元素是一项繁重的操作,因此不推荐使用这种方法。如果您有 30 个字段,那么您应该创建一个新组件,您可以在其中使用 ref 访问 input
        • 在这种情况下这很简单,但我会更新我的答案以反映这一点
        猜你喜欢
        • 1970-01-01
        • 2017-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-18
        • 2022-09-25
        • 2021-01-22
        相关资源
        最近更新 更多