首页 > 解决方案 > 输入速度过快时,React 输入字段现在可以工作

问题描述

我有这个简单的组件来检查用户名是否有效。它通过在输入值更改时查询 firebase 来实现。它有一个问题。当我在输入字段中输入太快时,其中的值没有足够的时间来改变,所以它只是错过了一些字符。这是代码:

对于状态管理,我使用 Recoil.JS。

组件代码:

export const UsernameInput = (props: {
  topLabel: string;
  bottomLabel?: string;
  placeholder?: string;
  className?: string;
  valueIn: any;
  valueOut: any;
  valid: any;
  validIn: boolean;
}) => {
  const usernameRef = db.collection("usernames");
  const query = usernameRef.where("username", "==", props.valueIn);

  useEffect(() => {
    query
      .get()
      .then((querySnapshot) => {
        if (querySnapshot.size >= 1) {
          props.valid(false);
        } else {
          props.valid(true);
        }
      })
  }, [props.valueIn]);

  function handleChange(event: any) {
    props.valueOut(event.target.value);
  }

  return (
    <InputSkeleton
      topLabel={props.topLabel}
      bottomLabel={props.bottomLabel}
      className={props.className}
    >
      <div className="input-username">
        <input type="text" onChange={handleChange} value={props.valueIn} />
        <span className="text">
          <span className={props.validIn ? "available" : "taken"}></span>
          {props.validIn ? "Available" : "Taken"}
        </span>
      </div>
    </InputSkeleton>
  );
};
<UsernameInput
  className="stretch"
  topLabel="Username"
  valueIn={formD.username}
  valueOut={(value: string) => {
    setFormD({ ...formD, username: value });
  }}
  valid={(value: boolean) => {
    setFormD({ ...formD, usernameValid: value });
  }}
  validIn={formD.usernameValid}
  bottomLabel="This will be your unique handle on xyz.com"
/>

标签: reactjstypescriptrecoiljs

解决方案


创建一个简单的去抖动函数,它以函数和时间(以秒为单位)为参数:

export function debounce(func, wait) {
    let timeout;

    return function executedFunction(...args) {
        const later = () => {
            timeout = null;

            func(...args);
        };
        clearTimeout(timeout);

        timeout = setTimeout(later, wait);
    };
}

然后在您的事件处理程序handleChange函数中使用它:

function handleChange(event: any) {
   event.preventDefault();
   // This means that you want to update the value after 500 milliseconds, i.e when you're sure that the user has stopped typing. You can extend this time to whatever figure you want
   debounce(props.valueOut(event.target.value), 500);
}

推荐阅读