我有一个组件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”的更新速度快,也许不是错误,但我想是错误的。
任何想法如何解决我的问题?谢谢。
答案 0 :(得分:1)
您是否考虑过添加debounce来真正快速地处理键入,并且仅在用户停止键入后才调用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
都是一种好习惯,更不用说遇到诸如您正在经历的错误之类的错误了。
编辑:
与其在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);
};