首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >textContentType=oneTimeCode不适用于iOS

textContentType=oneTimeCode不适用于iOS
EN

Stack Overflow用户
提问于 2020-11-07 00:29:54
回答 1查看 193关注 0票数 0

嗯,它过去是可以工作的,但在我修改了一些样式并添加了其他组件后,它停止了工作。

这是OTP的非工作版本:

代码语言:javascript
复制
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 && 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 && 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 && 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'
  },
});

这是工作版本:

代码语言:javascript
复制
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 && 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 && 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 && 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组件的位置。

EN

回答 1

Stack Overflow用户

发布于 2021-04-09 16:31:03

检查你发送的短信:在我的例子中,是法语的,

  • Veuillez saisir le code ${code} dans l'application is working
  • Veuillez entrer ce code dans l'application : ${code} is NOT working

我已经检查RN端几个小时了,最后改变短信是解决方案。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64718325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档