Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 当输入速度过快时,React输入字段现在不起作用_Reactjs_Typescript_Recoiljs - Fatal编程技术网

Reactjs 当输入速度过快时,React输入字段现在不起作用

Reactjs 当输入速度过快时,React输入字段现在不起作用,reactjs,typescript,recoiljs,Reactjs,Typescript,Recoiljs,我有一个简单的组件来检查用户名是否有效。它通过在输入值更改时查询firebase来实现。它有一个问题。当我在输入字段中输入得太快时,输入字段中的值没有足够的时间更改,因此它只会遗漏一些字符。代码如下: 对于状态管理,我使用Recoil.JS 组件代码: export const UsernameInput = (props: { topLabel: string; bottomLabel?: string; placeholder?: string; className?: st

我有一个简单的组件来检查用户名是否有效。它通过在输入值更改时查询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>
  );
};
export const UsernameInput=(道具:{
标签:字符串;
底部标签?:字符串;
占位符?:字符串;
类名?:字符串;
价值单位:任何;
估价输出:任何;
有效期:任何;
validIn:布尔型;
}) => {
const usernameRef=db.collection(“用户名”);
const query=usernameRef.where(“username”、“==”、props.valueIn);
useffect(()=>{
查询
.get()
.然后((querySnapshot)=>{
如果(querySnapshot.size>=1){
道具。有效(假);
}否则{
道具。有效(真);
}
})
},[props.valueIn]);
函数句柄更改(事件:任意){
props.valueOut(event.target.value);
}
返回(
{props.validIn?“可用”:“take”}
);
};
{
setFormD({…formD,用户名:value});
}}
有效={(值:布尔)=>{
setFormD({…formD,usernameValid:value});
}}
validIn={formD.usernameValid}
bottomLabel=“这将是您在xyz.com上的唯一句柄”
/>
创建一个简单的去盎司函数,将函数和时间(以秒为单位)作为参数:

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);
}

将此变量置于
UsernameInput
函数外部

const WAIT_INTERVAL = 1000;
编辑您的手柄更改为此

componentWillMount() {
    this.timer = null;
}

function handleChange(event: any) {
    clearTimeout(this.timer);
    this.timer = setTimeout(props.valueOut(event.target.value), WAIT_INTERVAL);
}

Princewill的想法是正确的,但是实现需要一些调整。具体来说,您需要在多次调用
debounce
时保留计时器句柄,并且
debounce
的参数需要是实际函数。使用普通函数并不能做到这一点,因为每次调用都会产生不同的本地超时句柄,并且旧句柄永远不会被取消或更新

我建议调整或使用useHooks中的钩子。这使用useffect来利用React的effect unmounting来清除任何先前设置的超时,并且总体上非常清楚

const{valueIn,valueOut}=props;
const[username,setUsername]=useState(valueIn);
//在每个事件中,更新`username'`
const handleChange=useCallback(
(event:any)=>setUsername(event.target.value),
[设置用户名]
);
//收集对用户名的更改并将debouncedUsername更改为最新
//500毫秒内未进行更改后的值。
const debouncedUsername=useDebounce(用户名,500);
//每次debouncedUsername更改时,运行所需的回调
useffect(()=>{
如果(debouncedUsername!==valueIn){
valueOut(debouncedUsername);
}
},[valueIn、valueOut、debouncedUsername]);
这里的想法是:

  • 您可以通过useState保留字段状态的实时更新副本
  • 您可以通过useDebounce保留字段状态的延迟更新副本
  • 当延迟更新的副本最终更改时,useEffect将触发valueOut回调。按照构造,这将在
    用户名更改后触发,但在500毫秒内不会再次更改

  • 此外,您还需要将字段的
    值设置为
    用户名
    ,而不是
    中的值
    ,以便字段能够实时更新,而不是延迟更新。

    问题仍然存在。问题仍然存在。救命!非常感谢。