我正在注册屏幕上工作,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;
有理论认为这是 iOS 17 上的一个错误