反应本机useState同步

劳尔

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

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

有什么办法可以做到同步吗?

这是我当前的代码:

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

TextInput伪代码

 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)}/>
    ...
 }

编写快速返回用户名“ tarantino”的不同值:

tarantino-true | tarantino-错误

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

有什么想法可以解决我的问题吗?谢谢。

j

您是否考虑过添加去抖动来真正快速地处理键入,并且仅firebase.isUsernameAvailable 在用户停止键入后才调用端点?

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

// The debounced function that you call instead of checkUsername
const debouncedCheck = debounce(checkUsername, 500);

我看不出对await每个键击都是好的习惯,更不用说遇到诸如您所经历的错误之类的错误的可能性了。

编辑:

而不是尝试调用onChangepropuseEffect来代替。

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

    const [text, setText] = useState(null)

    const handleChange = async (value) => {
      const { onChange } = props;
      setText(value);
      await onChange(value);
    }
 
    return <NativeTextInput value={text} onChangeText={handleChange}/>
    ...
 }

这样,您无需usernameInputRef.current.getText();checkUsername方法中执行此操作,而可以仅使用username传入值作为参数。

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

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

    setIsUsernameAvailable(isUsernameAvailable);
};

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章