【问题标题】:React native: race condition in TextInput反应原生:TextInput 中的竞争条件
【发布时间】:2020-03-10 13:29:51
【问题描述】:

我遇到了 TextInput 的问题,它从用户那里获取输入,以及一个在 TextInput 中发送消息并清除输入的按钮。 所以整体流程是:

  1. TextInput 中的用户类型
  2. 在某些时候,用户按下了 Button(又名 TouchableOpacity)
  3. 将 TextInput 中的文本存储到临时缓冲区,然后清除 TextInput。
  4. 通过 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 不会被清除。 我认为这是因为:

  1. 用户点击发送 => 排队渲染,因为消息状态由 Button 的 onPress 中的 setMessage("") 更改
  2. 用户类型太早 => 排队渲染,因为消息由 TextInput 中的 onChangeText 处理程序更改。问题是来自先前状态的 setMessage 尚未真正处理。因此,此渲染与消息的先前值(即消息设置为 "" 之前的值)一起排队。

我尝试了 Promise、useEffect 和 useRef,但没有真正解决这个问题。如果有人知道如何解决这个问题,请告诉我。提前谢谢你。

【问题讨论】:

    标签: react-native react-hooks race-condition react-native-textinput


    【解决方案1】:

    对于这个用例,您应该使用 CallbackPromiseAsync/Await。我建议你使用 Promise

    onSendMessage = msg => {
        axios
          .post("/your-url", {
            msg
          })
          .then(function(response) {
            console.log(response);
            // ! You can clear the message here !
            setMessage("");
            // OR
            return new Promise(() => resolve(msg));
          })
          .catch(function(error) {
            console.log(error);
          });
      };
    

    类似的东西。使用的选择是你的:)

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2021-08-27
        • 2018-09-19
        • 1970-01-01
        • 2021-05-11
        • 2017-02-06
        • 2021-03-21
        • 1970-01-01
        • 1970-01-01
        • 2015-12-31
        相关资源
        最近更新 更多