#react-native #react-native-ios
#react-native #react-native-ios
Вопрос:
Ну, раньше это работало, но после того, как я изменил некоторые стили и добавил другие компоненты, оно перестало работать.
Это нерабочая версия OTP:
import React, { useContext, useEffect, useState } from 'react'
import { StyleSheet, View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import {SafeAreaView} from 'react-native-safe-area-context'
import styled from 'styled-components/native'
import { CodeField, Cursor, useBlurOnFulfill, useClearByFocusCell } from 'react-native-confirmation-code-field'
import SmsRetriever from 'react-native-sms-retriever'
import {Button} from '../../components/button/button'
import {Text} from '../../components/text'
import { Breakpoint } from '../../components'
import {useHttp} from '../../hooks/use-http/use-http'
import {authService} from '../../api/auth.service'
import {Auth} from '../../models/auth.model'
import { OTPScreenProps } from './otp.props'
import { extractOTP } from '../../utils/extract-otp'
import { message } from '../../utils/message-handler'
import { AuthContext } from '../../contexts/auth/auth.context'
import chevronLeftIcon from '../../assets/icons/chevron-left-icon.png'
import { TouchableOpacity } from 'react-native-gesture-handler'
const CELL_COUNT = 6
const Container = styled(SafeAreaView)`
flex: 1;
background-color: ${({theme}) => theme.colors.background.primary};
`
const Content = styled.View`
align-items: center;
z-index: 1;
padding-horizontal: ${({ theme }) => theme.spacing[7]}px;
`
const Keyboad = styled.KeyboardAvoidingView.attrs({
behavior: 'position'
})`
padding-bottom: 85px;
`
const BackButtonContainer = styled.View`
align-self: flex-start;
padding-horizontal: ${({ theme }) => theme.spacing[7]}px
padding-top: ${({ theme }) => theme.spacing[7]}px
z-index: 2;
`
const BackButton = styled.Image.attrs({
source: chevronLeftIcon
})`
width: 12px;
height: 21px;
tint-color: white;
`
export const OTPScreen = ({ route, navigation }: OTPScreenProps) => {
const phone = route.params amp;amp; route.params.phone || '6203221059'
const [firstOTPSent, setFirstOTPSent] = useState<boolean>(true)
const { setAuth } = useContext(AuthContext)
const [code, setCode] = useState('')
const ref = useBlurOnFulfill({ value: code, cellCount: CELL_COUNT })
const [inputProps, getCellOnLayoutHandler] = useClearByFocusCell({
value: code,
setValue: setCode,
})
const [sendOTP, { loading: sendingOTP }] = useHttp<{ message: string }>(
() => authService.sendOTP(phone),
async (_, err) => {
if (err) message.danger('otp.sentError')
else if(!firstOTPSent) message.info('otp.sent')
}
)
const [confirmOTP, { loading }] = useHttp<Auth>(
(otp: string) => authService.confirmOTP(phone, otp),
async (auth, err) => {
if (err) message.danger('otp.loginError')
else setAuth(auth)
}
)
useEffect(() => {
if(phone) {
sendOTP()
setFirstOTPSent(false)
}
}, [])
useEffect(() => {
if(sendingOTP) listenToSMS()
}, [sendingOTP])
const listenToSMS = async () => {
try {
const registered = await SmsRetriever.startSmsRetriever()
if (!registered) return
SmsRetriever.addSmsListener(event => {
if(event amp;amp; event.message) {
const otp = extractOTP(event.message)
if(otp) {
setCode(otp)
confirmOTP(otp)
}
}
SmsRetriever.removeSmsListener()
})
} catch (error) {}
}
return (
<Container>
<BackButtonContainer>
<TouchableOpacity onPress={() => navigation.goBack()}>
<BackButton />
</TouchableOpacity>
</BackButtonContainer>
<ScrollView keyboardShouldPersistTaps="handled">
<Keyboad>
<Content>
<Breakpoint spacing={12} />
<Text tx="otp.confirmIdentity" color="tertiary" preset="h5" bold/>
<Breakpoint spacing={14} />
<Text tx="otp.enterCode" color="tertiary" preset="h5" opacity={0.7} align="center">
<Text color="tertiary" preset="h5" bold> {phone.slice(-4)}</Text>
</Text>
<Breakpoint spacing={2} />
<Button
preset="link"
tx="otp.again"
textProps={{
color: '#71A1F4',
preset: 'h4',
bold: true,
opacity: 0.7
}}
onPress={sendOTP}
loading={sendingOTP}
/>
<Breakpoint spacing={16} />
<CodeField
ref={ref}
{...inputProps}
value={code}
rootStyle={styles.root}
onChangeText={setCode}
cellCount={CELL_COUNT}
keyboardType="number-pad"
textContentType="oneTimeCode"
onEndEditing={() => confirmOTP(code)}
renderCell={({index, symbol, isFocused}) => (
<View
onLayout={getCellOnLayoutHandler(index)}
key={index}
style={[styles.cellRoot, isFocused amp;amp; styles.focusCell]}>
<Text style={styles.cellText}>
{symbol || (isFocused ? <Cursor /> : null)}
</Text>
</View>
)}
/>
<Button
style={{ width: '100%' }}
onPress={() => confirmOTP(code)}
tx="otp.login"
disabled={code.length < 6}
textProps={{ uppercase: true }}
loading={loading}
/>
</Content>
</Keyboad>
</ScrollView>
</Container>
)
}
const styles = StyleSheet.create({
root: {
marginBottom: 36,
width: '75%',
height: 55
},
cellRoot: {
flex: 1,
marginHorizontal: 5,
justifyContent: 'center',
alignItems: 'center',
borderBottomColor: '#71A1F4',
borderBottomWidth: 2
},
cellText: {
color: 'white',
fontSize: 38,
textAlign: 'center',
},
focusCell: {
borderBottomColor: '#007AFF'
},
});
И это рабочая версия:
import React, { useContext, useEffect, useState } from 'react'
import { StyleSheet, Dimensions, View } from 'react-native'
import {SafeAreaView} from 'react-native-safe-area-context'
import styled from 'styled-components/native'
import { CodeField, Cursor, useBlurOnFulfill, useClearByFocusCell } from 'react-native-confirmation-code-field'
import SmsRetriever from 'react-native-sms-retriever'
import {Button} from '../../components/button/button'
import {Text} from '../../components/text'
import { Breakpoint } from '../../components'
import {useHttp} from '../../hooks/use-http/use-http'
import {authService} from '../../api/auth.service'
import {Auth} from '../../models/auth.model'
import { OTPScreenProps } from './otp.props'
import { extractOTP } from '../../utils/extract-otp'
import { message } from '../../utils/message-handler'
import { AuthContext } from '../../contexts/auth/auth.context'
import chevronLeftIcon from '../../assets/icons/chevron-left-icon.png'
import { TouchableOpacity } from 'react-native-gesture-handler'
const CELL_COUNT = 6
const Container = styled(SafeAreaView)`
background-color: ${({theme}) => theme.colors.background.primary};
height: 100%;
`
const Keyboad = styled.KeyboardAvoidingView.attrs({
behavior: 'padding'
})`
align-items: center;
height: ${Dimensions.get('window').height}px;
padding: 25px;
`
const BackButtonContainer = styled.View`
align-self: flex-start;
`
const BackButton = styled.Image.attrs({
source: chevronLeftIcon
})`
width: 12px;
height: 21px;
tint-color: white;
`
export const OTPScreen = ({ route, navigation }: OTPScreenProps) => {
const phone = route.params amp;amp; route.params.phone || '6203221059'
const [firstOTPSent, setFirstOTPSent] = useState<boolean>(true)
const { setAuth } = useContext(AuthContext)
const [code, setCode] = useState('')
const ref = useBlurOnFulfill({ value: code, cellCount: CELL_COUNT })
const [inputProps, getCellOnLayoutHandler] = useClearByFocusCell({
value: code,
setValue: setCode,
})
const [sendOTP, { loading: sendingOTP }] = useHttp<{ message: string }>(
() => authService.sendOTP(phone),
async (_, err) => {
if (err) message.danger('otp.sentError')
else if(!firstOTPSent) message.info('otp.sent')
}
)
const [confirmOTP, { loading }] = useHttp<Auth>(
(otp: string) => authService.confirmOTP(phone, otp),
async (auth, err) => {
if (err) message.danger('otp.loginError')
else setAuth(auth)
}
)
useEffect(() => {
if(phone) {
sendOTP()
setFirstOTPSent(false)
}
}, [])
useEffect(() => {
if(sendingOTP) listenToSMS()
}, [sendingOTP])
const listenToSMS = async () => {
try {
const registered = await SmsRetriever.startSmsRetriever()
if (!registered) return
SmsRetriever.addSmsListener(event => {
if(event amp;amp; event.message) {
const otp = extractOTP(event.message)
if(otp) {
setCode(otp)
confirmOTP(otp)
}
}
SmsRetriever.removeSmsListener()
})
} catch (error) {}
}
return (
<Container>
<Keyboad>
<BackButtonContainer>
<TouchableOpacity onPress={() => navigation.goBack()}>
<BackButton />
</TouchableOpacity>
</BackButtonContainer>
<Breakpoint spacing={12} />
<Text tx="otp.confirmIdentity" color="tertiary" preset="h5" bold/>
<Breakpoint spacing={14} />
<Text tx="otp.enterCode" color="tertiary" preset="h5" opacity={0.7} align="center">
<Text color="tertiary" preset="h5" bold> {phone.slice(-4)}</Text>
</Text>
<Breakpoint spacing={2} />
<Button
preset="link"
tx="otp.again"
textProps={{
color: '#71A1F4',
preset: 'h4',
bold: true,
opacity: 0.7
}}
onPress={sendOTP}
loading={sendingOTP}
/>
<Breakpoint spacing={16} />
<CodeField
ref={ref}
{...inputProps}
value={code}
rootStyle={styles.root}
onChangeText={setCode}
cellCount={CELL_COUNT}
keyboardType="number-pad"
textContentType="oneTimeCode"
onEndEditing={() => confirmOTP(code)}
renderCell={({index, symbol, isFocused}) => (
<View
onLayout={getCellOnLayoutHandler(index)}
key={index}
style={[styles.cellRoot, isFocused amp;amp; styles.focusCell]}>
<Text style={styles.cellText}>
{symbol || (isFocused ? <Cursor /> : null)}
</Text>
</View>
)}
/>
<Button
style={{ width: '100%' }}
onPress={() => confirmOTP(code)}
tx="otp.login"
disabled={code.length < 6}
textProps={{ uppercase: true }}
loading={loading}
/>
</Keyboad>
</Container>
)
}
const styles = StyleSheet.create({
root: {
marginBottom: 36,
width: '75%',
height: 55
},
cellRoot: {
flex: 1,
marginHorizontal: 5,
justifyContent: 'center',
alignItems: 'center',
borderBottomColor: '#71A1F4',
borderBottomWidth: 2
},
cellText: {
color: 'white',
fontSize: 38,
textAlign: 'center',
},
focusCell: {
borderBottomColor: '#007AFF'
},
});
Кроме того, я ничего не изменил, ничего не обновил. Единственное большое различие, которое я вижу между этими двумя версиями, заключается в том, что я добавил ScrollView, кроме того, я просто изменил некоторые стили и изменил позицию компонента KeyboardAvoidingView.
Ответ №1:
проверьте отправляемое вами SMS: в моем случае на французском,
Veuillez saisir le code ${code} dans l'application
работаетVeuillez entrer ce code dans l'application : ${code}
не работает
Я проверял RN в течение нескольких часов, и, наконец, изменение SMS было решением.
Комментарии:
1. это сработало и для меня! Большое спасибо. Похоже, что код должен быть в конце SMS и без каких-либо символов, как
:
перед ним. Просто взглянул, как выглядит мое банковское приложение SMS.2. ммм, не уверен, сообщение Apple похоже
Your Apple ID code is: 123456. Do not share it with anyone. @apple.com #123456 %apple.com