繁体   English   中英

React Native useState 同步

[英]React Native useState sync

我有一个带有状态“文本”的组件 TextInput,它表示它的值。 此外,我还有一个其他组件 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}
    />
  );
}

文本输入伪代码

 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”返回不同的值:

塔伦蒂诺 - 真实 | 塔伦蒂诺 - 假

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

任何想法如何解决我的问题? 谢谢你。

您是否考虑过添加去抖动以非常快速地处理输入,并且仅在用户停止输入后才调用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每一次击键都不是一个好习惯,更不用说遇到诸如您遇到的错误的可能性。

编辑:

与其在useEffect中调用onChange道具, useEffect试试这个。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM