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

tnkciper  于 2022-12-30  发布在  React
关注(0)|答案(2)|浏览(148)

我在ScrollView中有一个很大的表单,将keyBoardShouldPersistTaps设置为“handled”,并且在TextInput中调用onBlur时将输入的值保存到全局状态中(onChangeText保存到每个组件中的本地状态,以提高性能)。
当我的用户提交表单时,问题就出现了,如果他们点击submit按钮,同时仍然有一个textinput处于焦点状态(其中有值),那么submit调用将在没有按下submit按钮时处于焦点状态的textinput的值的情况下运行。
所有其他文本输入中的所有其他值都正确提交,因为状态有时间正确更新。
如何确保在调用submit函数之前更新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.在文本输入中输入内容
1.直接点击提交按钮
1.您不会看到在textinput中输入的内容,因为提交在状态从onBlur更新之前触发
复制工作“提交材料”的步骤:
1.在文本输入中输入内容
1.单击任何其他位置以关闭键盘
1.点击按钮,你会看到你输入到文本输入

xqkwcwgp

xqkwcwgp1#

**OLD CODE:**您不能执行以下操作吗?或者您必须使用另一个名为“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>
  );
}
i34xakig

i34xakig2#

尝试使用React.useCallback(()=>{},[])
下面是示例代码:

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

    //React.useCallback make sure that localValue has been updated before setGlobalValue while using onBlur
    const handleOnBlue = React.useCallback(()=>{
        setGlobalValue(localValue);
    },[localValue])

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

相关问题