【问题标题】:React Native custom passcode screenReact Native 自定义密码屏幕
【发布时间】:2021-04-18 06:27:03
【问题描述】:

我正在尝试创建自己的自定义密码屏幕,但不幸的是它无法正常工作。当我尝试按下任何按钮(数字和后退按钮)时,它们都不起作用。

我已尝试在控制台中登录密码变量,以查看在按下数字时是否记录了数字,但由于某种原因,除了 0 之外的所有数字都被记录了。

const[password,setPassword]=useState(['','','',''])

let numbers =[
      {id:1},
      {id:2},
      {id:3},
      {id:4},
      {id:5},
      {id:6},
      {id:7},
      {id:8},
      {id:9},
      {id:0},
    ]

const onPressNumber =(num)=>{
   let tempCode = password;
   for(var i=0;i<tempCode.length;i++){
     if(tempCode[i]==''){
       tempCode[i]=num;
       break;
     }else{
       continue;
    }
   }
   setPassword(tempCode)
}

const onPressBack =(num)=>{
      let tempCode = password;
      for(var i=tempCode.length-1;i>=0;i--){
        if(tempCode[i]!=''){
          tempCode[i]='';
          break;
        }else{
          continue;
        }
      }
      setPassword(tempCode)
}

return(

<View>
            
{
  password.map(p=>{
     let style =p != ''? 
       {width:15,
        height:15,
        borderRadius:15,
        backgroundColor:'blue'}
        :
        {width:15,
        height:15,
        borderRadius:15,
        backgroundColor:'white'}
            
            return <View style={style}></View>
           })
         }
</View>

<View style={{alignItems:'center',justifyContent:'center'}}>
<View style={styles.numbersContainer}>

  {numbers.map(num=>{
     return(
        <TouchableOpacity 
           style={styles.number} 
           key={num.id} 
           onPress={()=>{onPressNumber(num.id)}}>
                
        <Text style={styles.numberText}>{num.id}</Text>
              
        </TouchableOpacity>
        )
        })}
          
</View>
</View>

{password != ''?
    <View style={styles.button}>
            <TouchableOpacity onPress={()=>onPressBack()}>
            <Ionicons name="arrow-back" size={30} color="black" />            
            </TouchableOpacity>
    </View>
:null}

【问题讨论】:

    标签: react-native


    【解决方案1】:

    你犯的错误是你在 onPress 方法中改变状态数组

    let tempCode = password;
    

    改为使用扩展运算符来浅拷贝

    let tempCode = [...password];
    

    记住:在映射多个数据集时不要将重复的键分配给View,因为它不知道发生更改时要更新哪个视图。

    <View key={shouldBeUnique} />
    

    自从 ES6 下降以来,这一直是最流行的方法。它是 简短的语法,你会发现它在使用库时非常有用 比如 React 和 Redux 等,

    注意:这不能安全地复制多维数组。数组/对象 值是按引用而不是按值复制的。

    我做了很多改变,并为您在世博小吃中创建了工作示例。检查一下。

    世博小吃:https://snack.expo.io/@klakshman318/belligerent-celery

    import React, {useState, useEffect} from 'react';
    import { Text, View, FlatList, StyleSheet, TouchableOpacity } from 'react-native';
    
    // to generate serial number based on count as argument
    const getSerialNumbers = (count) => {
      const numbersArray = [];
      for(let i = 0; i < count; i++) {
        numbersArray.push({
          number:i.toString(),
          empty: false
        });
      }
      // to make even - which are not full rows will be added empty object with empty key set to true
      const fullRows = Math.floor(numbersArray.length/2);
      let lastRow = numbersArray.length-(fullRows*2);
      while (lastRow!==2 && lastRow!==0) {
          numbersArray.push({ _id: `blank-${lastRow}`, empty: true });
          lastRow++;
      }
      return numbersArray;
    }
    
    export default function App() {
    
      const [passwords, setPassword] = useState(['','','','']);
    
      useEffect(() => {
        // alert(JSON.stringify(passwords));
      }, [passwords]);
    
      const onPressNumber = (num) => {
        let tempPassCode = [...passwords];
        for(var i=0;i<tempPassCode.length;i++){
          if(tempPassCode[i]==''){
            tempPassCode[i]=num;
            break;
          }else{
            continue;
          }
        }
        setPassword(tempPassCode)
      }
    
      const onPressBack =(num)=>{
          let tempPassCode = [...passwords];
          for(let i=tempPassCode.length-1;i>=0;i--){
            if(tempPassCode[i]!=''){
              tempPassCode[i]='';
              break;
            }else{
              continue;
            }
          }
          setPassword(tempPassCode);
      }
    
      // Number Pad FlatList render each Item
      const renderNumPadBtnItem = ({item}) => {
        if(item.empty) {
          return (
            <TouchableOpacity onPress={() => onPressBack()} style={{flex:1, alignItems:'center', marginHorizontal:3, backgroundColor:'#B0D7FF', padding:12}}>
              <Text style={{color:'black', fontSize:18}}>Go Back</Text>
            </TouchableOpacity>
          );
        }
        return (
          <TouchableOpacity 
            onPress={()=> onPressNumber(item.number)}
            style={{flex:1, alignItems:'center', marginHorizontal:3, backgroundColor:'#ccc', padding:12}}
          >
            <Text style={{color:'black', fontSize:18}}>{item.number}</Text>
          </TouchableOpacity>
        );
      }
    
      // NumberPad FlatList
      const renderNumberKeyPad = () => {
        const numkeyPadData = getSerialNumbers(11);
        return (
          <FlatList 
            numColumns={3}
            ItemSeparatorComponent={() => (
              <View style={{padding:3}} />
            )}
            data={numkeyPadData}
            renderItem={renderNumPadBtnItem}
            keyExtractor={item => item.number}
          />
        );
      }
    
      const renderPassCodeData = () => {
    
      }
    
      return (
        <View style={styles.containerWrap}>
        
          <View style={styles.passCodeContainer}>      
            {passwords.map(pItem => {  
              return (
                <View 
                  key={pItem+Math.random()} 
                  style={[styles.passCodeBox, {
                    backgroundColor: pItem != '' ? '#96DED1' : 'white' 
                  }]}
                >
                  <Text style={{color:pItem ? 'white' : 'black', fontSize:16, opacity: pItem ? 1 : 0.2}}>
                    {pItem ? pItem : '0'}
                  </Text>
                </View>
              )
            })}
          </View>
    
          <View style={styles.spacingM12}>
            {renderNumberKeyPad()}
          </View>
    
        </View>
      )
    }
    
    const styles = StyleSheet.create({
      containerWrap: {
        flex: 1,
      },
      passCodeContainer: {
        backgroundColor:'#00A36C', 
        paddingVertical:12, 
        flexDirection:'row'
      },
      passCodeBox: {
        padding:12,
        alignItems:'center',
        marginHorizontal:6,
        flex:1,
      },
      spacingM12: {
        marginTop:12
      }
    });
    

    【讨论】:

    • 您好,非常感谢您的回答。该功能现在正在运行,但我唯一的问题是当我 console.log(password) 我得到 ["0", "0", "0", "0"] 而不是 0000
    • 这样做 - ['0','0','0','0'].join('');
    • 它会按照你的预期输出:'0000',而不是在你想要的地方使用这个字符串!
    • 哦,所以当向后端发送密码时,我将其作为 password.join('') 发送?
    • 是的,就是这样。它会通过加入给你字符串。 join('') 字符串意味着它不会在字符串之间添加空格。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多