提交表单时如何等待onBlur状态更新

How to wait for onBlur state update when submitting form

我在 ScrollView 中有一个大表单,其中 keyBoardShouldPersistTaps 设置为“已处理”,并且正在保存在 TextInput 中调用 onBlur 时输入到全局状态的值(onChangeText 保存到每个组件中的本地状态以性能更高)。

当我的用户提交表单时出现问题,如果他们点击提交按钮,同时仍然有一个文本输入(其中有值),提交调用是 运行 而没有来自按下提交按钮时聚焦的文本输入。

所有其他文本输入中的所有其他值都已正确提交,因为状态有时间正确更新。

如何确保在调用提交函数之前更新 onBlur 和 useState(我知道这是异步的)?

解释我的挑战的简化代码 (expo snack):

import * as React from 'react';
import { ScrollView, StyleSheet, Button, Alert, TextInput, Keyboard } from 'react-native';
import Constants from 'expo-constants';

export default function App() {
      const [globalValue, setGlobalValue] = React.useState('Useless Placeholder');
    const [localValue, setLocalValue] = React.useState(globalValue);

  return (
    <ScrollView keyboardShouldPersistTaps={"handled"} style={styles.container}>
    <TextInput
      style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
      onChangeText={text => setLocalValue(text)}
      value={localValue}
      onBlur={() => setGlobalValue(localValue)}
    />
            <Button
        title="Press me"
        onPress={() => {Keyboard.dismiss(); Alert.alert(globalValue);}}
      />
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

重现我的问题的步骤:

  1. 在文本输入中输入内容
  2. 直接点击提交按钮
  3. 您将看不到在文本输入中输入的内容,因为提交在状态从 onBlur 更新之前触发

重现有效“提交”的步骤:

  1. 在文本输入中输入内容
  2. 点击其他任何地方关闭键盘
  3. 点击按钮,您将看到您在文本输入中输入的内容

旧代码: 你不能像下面那样做,或者你必须使用另一个名为 'text' 的状态变量吗?

export default function App() {
  const placeHolder = "Useless Placeholder";
  const [value, onChangeText] = React.useState(placeHolder);

  return (
    <ScrollView keyboardShouldPersistTaps={"handled"} style={styles.container}>
    <TextInput
      style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
      onChangeText={text => onChangeText(text)}
      value={value}
      onBlur={() => {
        onChangeText(value || placeHolder);
      }}
    />
    <Button
        title="Press me"
        onPress={() => {Keyboard.dismiss(); Alert.alert(value);}}
    />
    </ScrollView>
  );
}

更新代码:这是我目前能看到的唯一方法

export default function App() {
  const placeHolder = 'Useless Placeholder';
  const [globalValue, setGlobalValue] = React.useState(placeHolder); 
  const [localValue, setLocalValue] = React.useState(globalValue);
    
  useEffect(() => {
    Keyboard.dismiss();
    if(placeHolder !== globalValue) {
      Alert.alert(globalValue);
    }      
  }, [globalValue]);

  return (
    <ScrollView keyboardShouldPersistTaps={"handled"} style={styles.container}>
      <TextInput
        style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
        onChangeText={text => setLocalValue(text)}
        value={localValue}
      />
      <Button
        title="Press me"
        onPress={() => {setGlobalValue(localValue)}}
      />
    </ScrollView>
  );
}