我正在尝试创建自己的自定义密码屏幕,但不幸的是它不起作用。当我尝试按下任何按钮(数字和后退按钮)时,它们都不起作用。
我尝试在控制台中登录密码变量,以查看按下数字时是否记录了数字,但由于某种原因,除 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}
答案 0 :(得分:1)
你犯的错误是你在 onPress 方法中改变了状态数组
let tempCode = password;
改为使用扩展运算符进行浅拷贝
let tempCode = [...password];
请记住:当您映射多个数据集时,不要为 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
}
});