React Native 自定义密码屏幕

时间:2021-04-18 06:27:03

标签: react-native

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

我尝试在控制台中登录密码变量,以查看按下数字时是否记录了数字,但由于某种原因,除 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}

1 个答案:

答案 0 :(得分:1)

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

let tempCode = password;

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

let tempCode = [...password];

enter image description here

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

<View key={shouldBeUnique} />
<块引用>

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

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

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

世博小吃: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
  }
});