Reputation: 793
I am trying to create my own custom passcode screen but unfortunately its not working. When i try to press on any of the buttons (numbers and back button) they do not work.
I have tried logging in the console the password variable to see if the numbers are getting logged when they are pressed but for some reason all the numbers get logged except the 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}
Upvotes: 0
Views: 613
Reputation: 1618
mistake that you made was you're mutating state array in your onPress methods
let tempCode = password;
instead use Spread Operator to Shallow copy
let tempCode = [...password];
Remember: do not assign duplicate keys to View
when you map multiple dataSets because it doesn't know which view to update when changes occurred.
<View key={shouldBeUnique} />
Ever since ES6 dropped, this has been the most popular method. It’s a brief syntax and you’ll find it incredibly useful when using libraries like React and Redux etc.,
Note: This doesn’t safely copy multi-dimensional arrays. Array/object values are copied by reference instead of by value.
i made lot of changes and created working example in expo snack for you. check it.
Expo Snack: 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
}
});
Upvotes: 1