react-native - 反应原生:TextInput 中的竞争条件
问题描述
我遇到了 TextInput 的问题,它从用户那里获取输入,以及一个在 TextInput 中发送消息并清除输入的按钮。所以整体流程是:
- 用户输入 TextInput
- 在某些时候,用户按下按钮(又名 TouchableOpacity)
- 将 TextInput 中的文本存储到临时缓冲区,然后清除 TextInput。
- 通过 api 发送文本。
代码如下:
{/* Message Input */}
<TextInput
style={styles.messageInput}
multiline
onChangeText={text => {
setMessage(text);
}}
value={message}
/>
{/* Send Button */}
<Button
title={"Send"}
onPress={() => {
const msg = message
onSendMessage(msg);
setMessage("");
}}
disabled={false}
style={styles.sendButton}
/>
当用户在点击发送按钮后过早输入时,我的问题就会出现。如果用户决定输入得太早,则 TextInput 不会被清除。我认为这是因为:
- 用户点击发送 => 排队渲染,因为消息状态由按钮的 onPress 中的 setMessage("") 更改
- 用户输入太快 => 排队渲染,因为 TextInput 中的 onChangeText 处理程序更改了消息。问题是来自先前状态的 setMessage 尚未真正处理。因此,此渲染与消息的先前值(又名消息设置为 "" 之前的值)一起排队。
我尝试了 Promise、useEffect 和 useRef,但没有真正解决这个问题。如果有人知道如何解决这个问题,请告诉我。先感谢您。
解决方案
useState 钩子是异步的,不会立即反映和更新,而是会触发重新渲染。因此,您不应将此值存储在像这样的常量中:const msg = message
.
我会创建一个异步函数,将输入发送到 api。(奖励:添加加载状态以通过禁用提交按钮向用户提供反馈)
const [isLoading, setIsLoading] = useState(false);
onSubmit = async () => {
setIsLoading(true);
const response = await fetch('url/action', settings);
if(response){
setIsLoading(false);
return response.json();
}
}
<TextInput
style={styles.messageInput}
multiline
onChangeText={text => {
setMessage(text);
}}
value={message}
/>
<Button
title={"Send"}
onPress={() => onSubmit()}
disabled={isLoading}
style={styles.sendButton}
/>
推荐阅读
- java - 如何在android studio中的设备每次旋转时仅在onCreate中运行一个功能
- scala - Spark Scala groupByKey 用于数据集错误类型不匹配
- python - 为什么我的 python 程序返回 ValueError?
- html - 如何在 ion-button 中自定义文本和按钮的对齐方式?
- wordpress - wp-graphql - 无法查询 acf globalOptions
- javascript - 在php中提交评论之前显示登录页面
- javascript - 为什么循环后数组越来越大?
- capacitor - Android Admob-Free 在电容器中设置 ADMob-ID
- kubernetes - 在 Helm 中将字符串转换为 Yaml
- python - 如何在pyshark中打印协议名称而不是相应的数字?