Javascript 反应本机useState同步

Javascript 反应本机useState同步,javascript,reactjs,react-native,asynchronous,async-await,Javascript,Reactjs,React Native,Asynchronous,Async Await,我有一个组件TextInput,其状态为“text”,表示其值。另外,我还有一个组件UsernameTextInput,它包装了TextInput并包含一个状态“isUsernameAvailable”,它指示是否允许在我的数据库中写入文本输入的当前值 由于useState是异步的,有时当用户键入的速度非常快时,与键入的用户名相对应的isUsernameAvailable是错误的。例如,用户名“tarantino”不可用,但有时,在我当前的代码中,它是可用的,因为useState是异步的,我没有

我有一个组件TextInput,其状态为“text”,表示其值。另外,我还有一个组件UsernameTextInput,它包装了TextInput并包含一个状态“isUsernameAvailable”,它指示是否允许在我的数据库中写入文本输入的当前值

由于useState是异步的,有时当用户键入的速度非常快时,与键入的用户名相对应的isUsernameAvailable是错误的。例如,用户名“tarantino”不可用,但有时,在我当前的代码中,它是可用的,因为useState是异步的,我没有正确处理它

有什么方法可以同步吗

这是我目前的代码:

function UsernameInput(props) {    
  const [isUsernameAvailable, setIsUsernameAvailable] = useState(undefined);

  const usernameInputRef = useRef(null);

  const previousValues = useRef(null);

  const checkUsername = async () => {
    const { firebase } = props;

    // Get the username
    const username = usernameInputRef.current.getText();

    
    // Check if the username is valid and available on the database
    const isUsernameAvailable = validateUsername(username) &&
                          (await firebase.isUsernameAvailable(username));

    setIsUsernameAvailable(isUsernameAvailable);
  };

  useEffect(() => {
    // Get the username from the text input
    const username = usernameInputRef.current.getText();

    if (
      previousValues.current?.username !== username &&
      previousValues.current?.isUsernameAvailable !== isUsernameAvailable
    ) {          
        console.log(`${username} - ${isUsernameAvailable}`)
        
        // Update previousValues reference
        previousValues.current = { username, isUsernameAvailable };
    }
  });

  return (
    <TextInput
      ref={usernameInputRef}
      onChange={checkUsername}
    />
  );
}
函数UsernameInput(props){
const[isUsernameAvailable,setIsUsernameAvailable]=useState(未定义);
const usernameInputRef=useRef(null);
const previousValues=useRef(null);
const checkUsername=async()=>{
const{firebase}=props;
//获取用户名
const username=usernameInputRef.current.getText();
//检查用户名是否有效且在数据库中可用
const isusernameavable=validateUsername(用户名)&&
(等待firebase.isUsernameAvailable(用户名));
setIsUsernameAvailable(isUsernameAvailable);
};
useffect(()=>{
//从文本输入中获取用户名
const username=usernameInputRef.current.getText();
如果(
previousValues.current?.username!==用户名&&
previousValues.current?.isUsernameAvailable!==isUsernameAvailable
) {          
console.log(`${username}-${isUsernameAvailable}`)
//更新以前的值引用
previousValues.current={username,isUsernameAvailable};
}
});
返回(
);
}
文本输入伪码

 TextInput(props, ref) {
    const getTextInput = () => text;

    const [text, setText] = useState(null)
    
    useEffect(() => {
        const { onChange } = props;
        if(text) onChange();   
    }, [text]);  
 
    return <NativeTextInput value={text} onChange={(e) => setText(e.nativeEvent.text)}/>
    ...
 }
TextInput(道具,参考){
常量getput=()=>文本;
const[text,setText]=useState(null)
useffect(()=>{
const{onChange}=props;
if(text)onChange();
},[正文];
return setText(e.nativeEvent.text)}/>
...
}
写入fast会为用户名“tarantino”返回不同的值:

塔伦蒂诺-真| 塔伦蒂诺-错

我认为这里的问题是UsernameInput“isUsernameAvailable”的状态更新速度比TextInput状态“text”快,可能不是错误,但我认为是错误


有什么办法解决我的问题吗?谢谢。

您是否考虑过添加一个可快速处理键入操作,并且仅在用户停止键入后调用
firebase.isusernameavable
端点

const checkUsername=async()=>{
const{firebase}=props;
//获取用户名
const username=usernameInputRef.current.getText();
//检查用户名是否有效且在数据库中可用
const isUsernameAvailable=validateUsername(用户名)和&(wait firebase.isUsernameAvailable(用户名));
setIsUsernameAvailable(isUsernameAvailable);
};
//您调用的取消公告的函数,而不是checkUsername
const debouncedCheck=debounce(checkUsername,500);
我不认为等待每一次击键都是一种好的做法,更不用说遇到错误的可能性了,比如你正在经历的错误

编辑:

不要在
useffect
中调用
onChange
属性,而要尝试此操作

TextInput(道具,参考){
常量getput=()=>文本;
const[text,setText]=useState(null)
常量handleChange=async(值)=>{
const{onChange}=props;
setText(值);
等待一次改变(价值);
}
返回
...
}
这样做,而不是这样做
usernameInputRef.current.getText()
checkUsername
方法中,只需使用作为参数传入的
username
值即可

const checkUsername=async(username)=>{
const{firebase}=props;
//检查用户名是否有效且在数据库中可用
const isUsernameAvailable=validateUsername(用户名)和&(wait firebase.isUsernameAvailable(用户名));
setIsUsernameAvailable(isUsernameAvailable);
};

我这样做是因为我想实时显示用户名的可用性。我还看到您正在将
onChange
道具传递到
TextInput
组件中,但您没有在
NativeInput
中的任何地方调用它。伪代码不完整,它是在useffect中调用的,当文本状态更新时。我会更新它。我已经测试了取消公告的呼叫,它工作得很好!所以它基本上是停止执行,直到它没有被调用,然后,在一段延迟后,调用原始函数,对吗?我想我的问题解决了!非常感谢。是的,这是总的想法。很高兴我能帮忙!