React Native Expo:选择文本输入时屏幕闪烁

问题描述 投票:0回答:1

我正在注册屏幕上工作,React Native Expo 中的 TextInput 不断闪烁。仅发生在 iPhone 14 Pro Max 设备中。我已经在多个模拟器和 iPhone XS Max 设备上对其进行了测试,但由于某种原因它运行良好。我还附上视频供参考:

原始树:

闪烁期间的树

代码如下

import {
  Ionicons,
  MaterialCommunityIcons,
  MaterialIcons,
} from '@expo/vector-icons';
import React, {useEffect, useRef, useState} from 'react';
import {
  Alert,
  Image,
  Keyboard,
  Pressable,
  SafeAreaView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import SDButton from '../components/ui/sdbuttons';
import Input from '../boilerplate/input';
import {useTheme} from '../boilerplate/theme';
import {useAppContext} from '../boilerplate/store';
import {
  sendPasswordResetEmail,
  signInWithEmailAndPassword,
} from 'firebase/auth';
import {doc, getDoc, updateDoc} from 'firebase/firestore';
import {auth, firestore, logout} from '../boilerplate/firebase';
import {marginViewVertical} from '../helpers/margins';
import {isEmailRegistered} from '../helpers/firestore';
import {TextInput} from 'react-native';

const SignIn = ({navigation}) => {
  const theme = useTheme();

  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [showPassword, setShowPassword] = useState(false);
  const [isEmailLocked, setIsEmailLocked] = useState(false);
  const [saving, setSaving] = useState(false);
  const [isExpanded, setIsExpanded] = useState(false);
  const [isForgotPasswordExpanded, setIsForgotPasswordExpanded] =
    useState(false);
  const context = useAppContext();

  const passwordRef = useRef();

  const loginCleanup = () => {
    console.log('cleaning up!');
    setEmail('');
    setPassword('');
    setIsEmailLocked(false);
    setSaving(false);
  };

  const handleForgotPassword = async () => {
    setSaving(true);
    await sendPasswordResetEmail(auth, email);
    setSaving(false);

    Alert.alert(
      'Are your sure?',
      'Are you sure you want to reset your password?',
      [
        {
          text: 'Yes',
          onPress: () => {
            Alert.alert(
              'Link Sent',
              'Please check your inbox, and if nothing has arrived please check your spam folder.',
              [
                {
                  onPress: () => {},
                },
              ],
            );
          },
        },

        {
          text: 'No',
        },
      ],
    );
  };

  const handleForgotPressed = () => {
    setIsExpanded(false);
    setIsForgotPasswordExpanded(true);
  };

  const checkEmail = async () => {
    try {
      setSaving(true);
      if (email === '') {
        Alert.alert('Log In Error', 'Please input email');
        setSaving(false);
      } else if (await isEmailRegistered(email)) {
        setShowPassword(false);
        setIsExpanded(true);
        setIsEmailLocked(true);
        setSaving(false);
      } else {
        Alert.alert('Log In Error', 'Email does not exist');
        setSaving(false);
      }
    } catch (e) {
      console.error('e', e);
      setSaving(false);
    }
  };

  const handleBackPressed = () => {
    if (isForgotPasswordExpanded) {
      setShowPassword(false);
      setIsExpanded(true);
      setIsForgotPasswordExpanded(false);
    } else if (isExpanded) {
      setIsExpanded(false);
      setIsEmailLocked(false);
    } else navigation?.goBack();
  };

  const doLogin = async () => {
    Keyboard?.dismiss();
    setSaving(true);
    if (email === '' || password === '') {
      Alert.alert('Log In Error', 'Please input email and password correctly');
      setSaving(false);
      return;
    }
    signInWithEmailAndPassword(auth, email, password)
      .then(async userCredentails => {
        const customerData = await getDoc(
          doc(firestore, 'users', userCredentails?.user?.uid),
        );
        const stripeSubscriptionEndDate =
          customerData?.data()?.userData?.stripeSubscriptionEndDate;
        const stripeCustomerId =
          customerData?.data()?.userData?.stripeCustomerId;
        const stripeSubscriptionId =
          customerData?.data()?.userData?.stripeSubscriptionId;

        if (!stripeCustomerId || !stripeSubscriptionId) {
          if (logout) await logout();
          updateDoc(doc(firestore, 'users', userCredentails?.user?.uid), {
            token: '',
          });
          context?.setProfile(undefined);
          context?.setIsAuthed(false);
          alert('You do not have a valid Sit Down subscription');
        } else if (new Date() > new Date(stripeSubscriptionEndDate)) {
          if (logout) await logout();
          updateDoc(doc(firestore, 'users', userCredentails?.user?.uid), {
            token: '',
          });
          context?.setProfile(undefined);
          context?.setIsAuthed(false);
          alert('Your subscription has ended!');
        }
        loginCleanup();
      })
      .catch(e => {
        console.error(e?.code);
        if (e?.code) alert('Please check your email and password');
        setSaving(false);
      });
  };

  return (
    <SafeAreaView
      style={{
        flex: 1,
        backgroundColor: theme.primaryBackground,
      }}>
      <View
        style={{
          flexDirection: 'row',
          justifyContent: 'space-between',
          width: '100%',
          marginTop: '1.5%',
          paddingHorizontal: '4%',
          alignItems: 'center',
        }}>
        <Image
          source={require('../assets/login-icon.png')}
          style={{
            width: 35,
            height: 35,
          }}
          cachePolicy={'memory-disk'}
        />
        <Pressable onPress={handleBackPressed}>
          <Ionicons name="close-circle" color="white" size={32} />
        </Pressable>
      </View>

      <View
        style={{
          flex: 1,
          justifyContent: 'center',
          paddingHorizontal: 50,
          paddingLeft: 20,
        }}>
        <View style={{width: '100%', paddingHorizontal: 5}}>
          <Text
            style={{
              color: 'white',
              fontSize: 18,
              fontFamily: context?.helv600,
            }}>
            {isForgotPasswordExpanded
              ? 'Request a Password Reset Link'
              : 'Log In'}
          </Text>
          {!isForgotPasswordExpanded && (
            <TouchableOpacity onPress={() => navigation?.navigate('SignUp')}>
              <Text
                style={{
                  color: '#88ffdc',
                  fontSize: 15,
                  marginTop: 10,
                  fontFamily: context?.helv500,
                }}>
                or Join Now
              </Text>
            </TouchableOpacity>
          )}
        </View>
        {marginViewVertical('10%')}

        <View
          style={{
            alignItems: 'center',
            justifyContent: 'space-between',
            alignSelf: 'center',
            width: '100%',
            borderBottomColor: '#fff',
            flexDirection: 'row',
          }}>
          <View
            style={{
              flex: 1,
              width: '100%',
              padding: 5,
              alignContent: 'center',
              flexDirection: 'row',
              alignSelf: 'center',
              marginBottom: 10,
              // borderWidth: 1,
              // borderColor: 'white',
            }}>
            <MaterialCommunityIcons
              name="email-outline"
              size={24}
              color="#fff"
            />
            <View style={{width: 10}} />
            <TextInput
              style={[
                styles.input,
                {
                  color: isEmailLocked ? '#898b97' : 'white',
                },
              ]}
              keyboardType={'email'}
              autoComplete={'off'}
              autoCapitalize={'none'}
              autoCorrect={false}
              value={email}
              onChangeText={setEmail}
              placeholder={'E-mail, required'}
              placeholderTextColor={'#898b97'}
              editable={!isEmailLocked}
            />
            {/* <Input
              placeholder="E-mail, required"
              placeholderTextColor={'#898b97'}
              onChange={setEmail}
              value={email}
              isAutoCorrect={false}
              autoCapitalize={'none'}
              keyboardType={'email-address'}
              locked={isEmailLocked} 
            />*/}
          </View>
        </View>

        {isExpanded && (
          <>
            <View
              style={{
                justifyContent: 'center',
              }}>
              <View
                style={{
                  alignItems: 'center',
                  justifyContent: 'space-between',
                  alignSelf: 'center',
                  width: '100%',
                  borderBottomColor: '#fff',
                  //borderBottomWidth: 1,
                  flexDirection: 'row',
                  marginTop: 10,
                  marginBottom: 10,
                }}>
                <View
                  style={{
                    flex: 1,
                    padding: 5,
                    alignContent: 'center',
                    flexDirection: 'row',
                    justifyContent: 'flex-start',
                  }}>
                  <MaterialIcons name="lock-outline" size={24} color="#fff" />
                  <View style={{width: 10}} />
                  <TextInput
                    style={[
                      styles.input,
                      {
                        flex: 1,
                        width: '100%',
                        color: '#fff',
                      },
                    ]}
                    autoComplete={'off'}
                    autoCapitalize={'none'}
                    autoCorrect={false}
                    value={password}
                    onChangeText={setPassword}
                    placeholder={'Password, required'}
                    placeholderTextColor={'#898b97'}
                    secure={!showPassword}
                  />
                  {/* <Input
                    secure={!showPassword}
                    placeholder="Password, required"
                    placeholderTextColor={'#898b97'}
                    onChange={setPassword}
                    value={password}
                    autoCapitalize={'none'}
                    style={{
                      flex: 1,
                      width: '100%',
                      marginLeft: 10,
                      color: '#fff',
                    }}
                    inputRef={passwordRef}
                  /> */}
                </View>
                <Ionicons
                  style={{position: 'absolute', right: -20, bottom: 30}}
                  onPress={() => setShowPassword(!showPassword)}
                  name={showPassword ? 'ios-eye' : 'ios-eye-off'}
                  size={24}
                  color="#898b97"
                />
              </View>
              <TouchableOpacity
                style={{width: '100%'}}
                onPress={handleForgotPressed}>
                <Text
                  style={{
                    color: '#00FFCD',
                    fontSize: 14,
                  }}>
                  Forgot password?
                </Text>
              </TouchableOpacity>
            </View>
            {marginViewVertical(25)}
          </>
        )}
        {/* /////////////////////////////////////////////////////////////////////////////////////////// */}

        <View
          style={{
            justifyContent: 'center',
            marginStart: 40,
          }}>
          <SDButton
            loading={saving}
            text={
              isForgotPasswordExpanded
                ? 'Submit'
                : !isExpanded
                ? 'Continue'
                : 'Log In'
            }
            backgroundColor="#00FFCD"
            textColor="black"
            my={20}
            blurOnSubmit={false}
            onPress={() => {
              isForgotPasswordExpanded
                ? handleForgotPassword()
                : !isExpanded
                ? checkEmail()
                : doLogin();
            }}
          />
        </View>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  input: {
    alignItems: 'center',
    justifyContent: 'space-between',
    alignSelf: 'center',
    width: '88%',
    borderBottomColor: '#fff',
    borderBottomWidth: 1,
    marginBottom: 20,
    color: 'white',
    flexDirection: 'row',
    paddingBottom: 5,
    fontSize: 18,
  },
});

export default SignIn;

javascript react-native mobile expo react-native-textinput
1个回答
0
投票

有理论认为这是 iOS 17 上的一个错误

更多信息:https://github.com/facebook/react-native/issues/39411

© www.soinside.com 2019 - 2024. All rights reserved.