React Native pincode lock screen create. useState error - reactjs

I am trying to create a mobile lock screen with numbers to user for entering the pincode.
when the user press the number buttons values should be entered to the array that I have created.
when the numbers are entered, a style property is changed.
here is the code
import React from "react";
import { Alert, StyleSheet, Text, Touchable, TouchableHighlight, TouchableOpacity,useState, View } from "react-native";
import Loading from './Loading';
const Buttons = () => {
this.state = {
passcode: ['','','','']
}
_presControl = num =>{
let tempCode = this.state.passcode;
for(var i = 0; i<tempCode.length;i++){
if(tempCode[i] == ''){
tempCode[i] = num;
break;
}else{
continue;
}
}
this.setState({passcode:tempCode});
};
let nopad = [
{id:1},
{id:2},
{id:3},
{id:4},
{id:5},
{id:6},
{id:7},
{id:8},
{id:9},
{id:0}
];
return(
<View >
<View style={styles.boxcontaner} >
{this.state.passcode.map(p =>{
let style= p !=''? styles.box2:styles.box1;
return <View style={style}></View>
})}
</View>
<View style={styles.noBox}>
{nopad.map(num =>{
return(
<TouchableOpacity style={styles.box}
key={num.id}
onPress={this._presControl(num.id)} >
<Text style={styles.title}>{num.id}</Text>
</TouchableOpacity>
);
})}
</View>
</View>
);
}
const styles = StyleSheet.create({
box1: {
width:13,
height:13,
borderRadius:13,
borderWidth:1,
borderColor:'gray'
},
box2: {
width:13,
height:13,
borderRadius:13,
borderWidth:1,
borderColor:'gray',
backgroundColor:'red'
},
box: {
width:70,
height:70,
borderRadius:70,
borderWidth:1,
borderColor:'#F2F3F4',
alignItems:'center',
backgroundColor:'#F2F3F4',
justifyContent:'center',
alignItems:'center'
},
boxcontaner:{
flexDirection:'row',
alignItems:'center',
justifyContent:'space-between',
marginLeft:40,
marginRight:40,
marginTop:10,
},
noBox:{
alignItems:'center',
justifyContent:'center',
marginTop:100,
flexDirection:'row',
flexWrap:'wrap',
marginLeft:20,
width:270,
height:200,
}
});
export default Buttons;
But when I run the code it says
_this._presControl is not a function. (In '_this._presControl(num.id)', '_this._presControl' is undefined)
what is the error. How can I solve this please ?

You need to create a copy of your array so that you can update the state when a user enters the pin.
_presControl = num =>{
let tempCode = this.state.passcode;
for(var i = 0; i<tempCode.length;i++){
if(tempCode[i] == ''){
tempCode[i] = num;
break;
}else{
continue;
}
}
var newPinCode = [...tempCode];
this.setState(newPinCode);
};

You can not use class methods inside of body of the functional component. Instead you should call you function like that:
<TouchableOpacity
style={styles.box}
key={num.id}
onPress={()=>_presControl(num.id)} >
<Text style={styles.title}>{num.id}</Text>
</TouchableOpacity>

Related

How to save the QR Data and copy my clipboard?

I just have some question.
First, I'm beginner... Very sorry.
I have been developed the react-native app (iOS) for recognize the QR Code.
I already have been succeed the recognize the QR Code on my App.
But My Plan is..
First, I scan the QR Code and I want to save the QR data.
For the purpose, there are many QR Code in the warehouse above many box and it is included Serial Number.
After scanning, I will continue the scan until I want to stop it. (In conclusion, I scan many times.)
I just thought "Let's save the Serial Number at array.
Second, I save the serial number through the scanning and I want to copy our clipboard.
Also, I want to print in my App.
How can I implement this? I have no idea about that.
Code is here.
import { StatusBar } from 'expo-status-bar';
import React, {useState, useEffect} from 'react'
import { StyleSheet, Text, View, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
export default function App() {
const [hasPermisson, setHasPermisson] = useState(null);
const [scanned, setScanned] = useState(false);
const [text, setText] = useState('Not yet scanned')
const askForCameraPermisson = () => {
(async () => {
const {status} = await BarCodeScanner.requestPermissionsAsync();
setHasPermisson(status == 'granted')
})()
}
useEffect(() => {
askForCameraPermisson ();
}, [])
const handleBarCodeScanned = ({type, data}) => {
setScanned(true);
setText(text);
state = {
sn : [
{
type : type,
data : data
},
{
type : type,
data : data
}
]
}
console.log(state)
}
if (hasPermisson === null) {
return (
<View style={styles.container}>
<Text>Requesting for camera permisson</Text>
<StatusBar style="auto" />
</View>
)
}
if(hasPermisson === false) {
return (
<View style={styles.container}>
<Text>No acess to camera</Text>
<Button title={'Allow Camera'} onPress={() => askForCameraPermisson()}/>
</View>
)
}
return (
<View style={styles.container}>
<View style={styles.barcodebox}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style = {{ height:400, width:400}} />
</View>
<Text style={styles.maintext}>{text}</Text>
{scanned && <Button title={'scan again?'} onPress={( ) => setScanned(false)} color='tomato'/>}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
barcodebox: {
alignItems: 'center',
justifyContent: 'center',
height: 300,
width:300,
overflow:'hidden',
borderRadius:30,
backgroundColor:'tomato'
},
maintext: {
fontSize :16,
margin:20
}
});

React native, how to check arrays are equal or not

I have created pin code lock screen using react native.
you can see the code with emulator here - https://snack.expo.dev/#codewithbanchi/pincode
default pin is 1234 and it is assigned to an array.
Then I take the inputs from user and assign it to an another array.
Then I wrote this for checking if the user entered pin is equal to the default pin.
if(passcode===defaultCode){
alert("Login sucssesfull");
}else{
alert("Login failed");
}
but each time user touched on a button, alert comes up "Lofin failed''
What went wrong here
I am defining my complete code here and also You can go to above expo link to watch it with the emulator.
import React from "react";
import { Alert, StyleSheet, Text, Touchable, TouchableHighlight, TouchableOpacity,useState, View } from "react-native";
import Loading from './Loading';
const Buttons = () => {
const defaultCode = React.useState(['1','2','3','4'])
const [passcode , setPasscode] = React.useState(['','','',''])
const presControl = num =>{
let tempCode = [...passcode];
for(var i = 0; i<tempCode.length;i++){
if(tempCode[i] == ''){
tempCode[i] = num;
break;
}else{
continue;
}
}
setPasscode(tempCode);
}
if(passcode===defaultCode){
alert("Login sucssesfull");
}else{
alert("Login failed");
}
const clearPress = () =>{
let tempCode = [...passcode]
for(var i = tempCode.length-1;i>=0;i--){
if(tempCode[i] != ''){
tempCode[i]='';
break;
}else{
continue;
}
}
setPasscode(tempCode);
};
let nopad = [
{id:1},
{id:2},
{id:3},
{id:4},
{id:5},
{id:6},
{id:7},
{id:8},
{id:9},
{id:0}
];
return(
<View >
<View style={styles.boxcontaner} >
{passcode.map(p =>{
return <View style={p !=''? styles.box2:styles.box1}></View>
})}
</View>
<View style={styles.noBox}>
{nopad.map(num =>{
return(
<TouchableOpacity style={styles.box}
key={num.id}
onPress={()=>presControl(num.id)} >
<Text style={styles.title}>{num.id}</Text>
</TouchableOpacity>
);
})}
</View>
<TouchableOpacity onPress={clearPress} style={styles.deleter} >
<Text style={styles.title}> x
</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
title: {
fontSize:40,
justifyContent:'center',
marginTop:5,
},
box1: {
width:13,
height:13,
borderRadius:13,
borderWidth:1,
borderColor:'gray'
},
box2: {
width:13,
height:13,
borderRadius:13,
borderWidth:1,
borderColor:'gray',
backgroundColor:'red'
},
box: {
width:70,
height:70,
borderRadius:70,
borderWidth:1,
borderColor:'green',
alignItems:'center',
backgroundColor:'#F2F3F4',
justifyContent:'center',
},
boxcontaner:{
flexDirection:'row',
alignItems:'center',
justifyContent:'space-between',
marginLeft:40,
marginRight:40,
marginTop:10,
},
noBox:{
alignItems:'center',
justifyContent:'center',
marginTop:100,
flexDirection:'row',
flexWrap:'wrap',
marginLeft:20,
width:270,
height:200,
},
deleter:{
width:70,
height:70,
borderRadius:70,
borderWidth:1,
borderColor:'green',
alignItems:'center',
backgroundColor:'#F2F3F4',
marginLeft:190,
marginTop:10
}
});
export default Buttons;
arrays are reference types , read this link please - https://masteringjs.io/tutorials/fundamentals/compare-arrays , you can use this code :
const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [1, 2, 3];
function arrayEquals(a, b) {
return Array.isArray(a) &&
Array.isArray(b) &&
a.length === b.length &&
a.every((val, index) => val === b[index]);
}
arrayEquals(a, b); // false
arrayEquals(a, c); // true
https://snack.expo.dev/lmKFsz5J6 finished example

React native | websocket reload on rerender

I'm building small application about smart home using websocket. When i press device icon to toggle it, websocket sends message and updates state device is enabled or not. Problem is after updating component, it creates new websocket connection, not saving old one. Can anyone give some advice? What am i doing wrong?Better to use other npm lib? Here is code:
`
import React, { useRef, useState,useEffect } from 'react'
import { StyleSheet, Text, View, Pressable} from 'react-native'
import LightBulbOn from '../../assets/icons/light-bulb.svg'
import Power from '../../assets/icons/power.svg'
export default function Light({ ip,id,openModal }) {
const client = React.useRef()
useEffect(() => {
client.current = new WebSocket('ws://192.168.0.107/ws')
client.current.onopen = (message) => {
let data = JSON.parse(message.data)
alert(data)
let arr = [...devices]
arr[0].condition = data.light1
arr[1].condition = data.light2
setDevices(arr)
}
client.current.onmessage = message =>{
let data = JSON.parse(message.data)
let arr = [...devices]
arr[0].condition = data.light1
arr[1].condition = data.light2
setDevices(arr)
}
client.current.onerror = message =>{
alert(message)
}
},[ip])
function sendMessage(id){
if(!client.current) {
alert('not client')
// client.current = new WebSocket('ws://192.168.0.105/ws')
return
}
let message = devices[id].condition?'->off':'->on'
client.current.send("light" + devices[id].id + message)
}
const [devices, setDevices] = useState([
{
id: 1,
deviceName: 'ნათურა 1',
condition: 0,
},
{
id: 2,
deviceName: 'ნათურა 2',
condition: 0
}
])
return (
<View style={styles.container} >
<Pressable style={styles.lightContainer} onLongPress={()=>openModal(id)} onPress = {()=> sendMessage(0)}>
<View style={styles.containerRow}>
<LightBulbOn width='30' height='30' />
<Power width='20' height='20' />
</View>
<View style={styles.description}>
<Text style={{ fontWeight: 'bold' }}>{devices[0].deviceName}</Text>
<Text>{devices[0].condition?'ჩართული':'გამორთული'}</Text>
</View>
</Pressable>
<Pressable style={styles.lightContainer} onLongPress={()=>openModal(id)} onPress = {()=> sendMessage(1)}>
<View style={styles.containerRow}>
<LightBulbOn width='30' height='30' />
<Power width='20' height='20' />
</View>
<View style={styles.description}>
<Text style={{ fontWeight: 'bold' }}>{devices[1].deviceName}</Text>
<Text>{devices[1].condition?'ჩართული':'გამორთული'}</Text>
</View>
</Pressable>
</View>
)
}
`
Thanks in advance
Suggest you can try this one instead:
https://github.com/Sumit1993/react-native-use-websocket
And if you pass nothing to useRef, it will return you undefined that can not serializable which might cause the problem.

set Multiple state Id for custom component in React Native

I have implemented custom inputBox component. So When I am using this component first time then it is working fine and when I am using multiple time in one page then data is prepopulate to next component.
Custom component:
import React, { createRef } from 'react';
import {
View,
TextInput,
Alert,
Text,
StyleSheet
} from "react-native";
class BoxInput extends React.Component {
constructor(props) {
super(props)
this.state = {
digit1: '',
digit2: '',
digit3: '',
...props
}
this.digit1Ref = createRef()
this.digit2Ref = createRef()
this.digit3Ref = createRef()
}
componentDidMount() {
this.digit1Ref.current.focus()
}
componentDidUpdate(prevProps) {
if (this.state.digit1 && this.state.digit2 &&
this.state.digit3
}
saveText(text, key) {
this.setState({ ...this.state, [key]: text }, () => {
if (text) {
key == 'digit1' ? this.digit2Ref.current.focus() : null
key == 'digit2' ? this.digit3Ref.current.focus() : null
key == 'digit3'
}
const boxInputValue = this.state.digit1 + this.state.digit2 + this.state.digit3
this.props.onBoxInput(boxInputValue)
});
}
render() {
return (
<>
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit1Ref} style={styles.boxStyle} value={this.state.digit1} onChangeText={(text) => this.saveText(text, 'digit1')} />
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit2Ref} style={styles.boxStyle} value={this.state.digit2} onChangeText={(text) => this.saveText(text, 'digit2')} />
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit3Ref} style={styles.boxStyle} value={this.state.digit3} onChangeText={(text) => this.saveText(text, 'digit3')} />
</>
)
}
}
const styles = StyleSheet.create({
boxStyle: {
marginTop: 20,
height: 57,
width: 50,
borderRadius: 10,
borderWidth: 1,
borderColor: '#F1F5F9',
backgroundColor: '#F1F5F9',
fontSize: 20,
lineHeight: 40,
paddingHorizontal: 15,
textAlign: 'center'
}
})
export default BoxInput;
import React, { createRef } from 'react';
import styles from './style';
import {
View,
TextInput,
Alert
} from "react-native";
import { connect } from "react-redux";
import * as Animatable from 'react-native-animatable';
import BoxInput from "../../../../md-components/atoms/boxinput"
class MPINScreen extends React.Component {
constructor(props) {
super(props)
this.state = {
confirmMpinEnable: true,
...props
}
this.codes = [{
value: '+91',
}]
}
componentDidUpdate(prevProps) {
if (this.state.mpinValue.split("").length == 3 &&
prevProps.success_msg != this.props.success_msg && this.props.success_msg == 'verified') {
NavigationService.navigate(this.props.navigation, 'MPINVerifyOnboarding')
}
}
handleSubmit = () => {
if (this.state.mpinValue != this.state.confirmMpinValue) {
Alert.alert(
"Error",
"MPIN is not machted",
[
{ text: "OK" }
],
{ cancelable: false }
);
} else {
this.props.verifyMpin({
"mpin": this.state.mpinValue,
phoneNumber: this.props.mobileNumber
})
}
}
mpinConfirmation = () => {
if (this.state.mpinValue.split("").length != 6) {
Alert.alert(
"Error",
"Please insert 6 digit mpin",
[
{ text: "OK" }
],
{ cancelable: false }
);
}else{
this.setState({
confirmMpinEnable: false,
});
}
}
mpinText = (args) => {
this.setState({
mpinValue: args,
});
}
confirmMpinText = (args) => {
this.setState({
confirmMpinValue: args,
});
}
render() {
return (
<>
<HeaderComponent backgroundColor="#E5E5E5" showLeftIcon={true} showRightIcon={false} />
<View style={styles.container}>
<Text style={[styles.textInfo, styles.textTitle]}>We are almost there!</Text>
<View style={styles.imageWrapper}>
<Animatable.View animation="slideInDown" iterationCount={1} style={styles.centerIconWrap}>
<Image style={styles.centerIcon} source={mpin_card} />
</Animatable.View>
</View>
{this.state.confirmMpinEnable ?
<Text style={[styles.textInfo]}>Setup your MPIN</Text> : <Text style={[styles.textInfo]}>Confirm your MPIN</Text>
}
{this.state.confirmMpinEnable ?
<View style={styles.rowWrap}>
<BoxInput id="catFood1" onBoxInput={this.mpinText} />
</View>:
<View style={styles.rowWrap}>
<BoxInput id="catFood2" onBoxInput={this.confirmMpinText} />
</View>
}
<View style={styles.marginBottom}>
<Text style={[styles.mpinNote]}>M-PIN is a short 6-digit PIN that you have to set for</Text>
<Text style={[styles.mpinNote]}>our mandatory Two-Factor Authentication</Text>
</View>
<View style={styles.bottomBtnSyle}>
<View style={styles.multipleBtnStyle}>
<Button onPress={this.handleBack}>{"Back"}</Button>
</View>
{this.state.confirmMpinEnable ?
<View style={styles.multipleBtnStyle}>
<Button onPress={this.mpinConfirmation} >{"Confirm"}</Button>
</View> :
<View style={styles.multipleBtnStyle}>
<Button onPress={this.handleSubmit} >{"Save & Continue"}</Button>
</View>
}
</View>
</View>
</>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MPINScreen);
when I am click on confirm button then hide and display . But in second component data is prepopulating which i was inserted.
in this screen shot data is prepopulate but i want this empty, Because user has to insert again. but it is taking same value from previous state. how we can use multiple time same component in one page.
General idea:
Create a property in MPINScreen state that is changing (incrementing) every attempt (you can call it attempt) and pass it as prop to BoxInput.
In BoxInput create a reset function (that will clean the values of the text inputs and focus the first input). On componentDidUpdate check if attempt prop changed. If true - save the new value in BoxInput state and call "reset".

setState not toggle value in react native

i am having function that toggle the state variables value.
the initial value of the state variable is false
Here is my function...
expandLists(label){ // "label" is a state variable that passed as a string
let result = new Boolean();
console.log(this.state);
if(this.state.label){
result=false;
console.log('Result = false');
}
else{
result=true;
console.log('Result = true');
}
this.setState({[label]: result},console.log(this.state))
}
In the above expression at inital state the value is changed to false then it is not changing to true.
I have also tried.. the below method...
expandLists(label){
this.setState( preState => ({label: !this.preState.label}),console.log(this.state))
}
If you pass the label parameter as a string, then try this:
expandLists(label){ // "label" is a state variable that passed as a string
let result = new Boolean();
console.log(this.state);
if(this.state[label]){
result=false;
console.log('Result = false');
}
else{
result=true;
console.log('Result = true');
}
this.setState({[label]: result},console.log(this.state))
}
So the difference is in checking if the current value is truethy. In stead of using this.state.label, use this.state[label].
Check this way as you said "label" param type of string
if(this.state.label == "true"){
...
}
or
if(this.state[label]){
...
}
Easy way to achieve this is
toggleLabelValue = (label) => {
this.setState({ [label]: !this.state[label] }, () =>
console.log(this.state)
);
};
Try toggling state in this way:
import React from 'react';
import {
View,
Button,
} from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
label: false
}
}
changeLabel = (currentLabel) => {
this.setState({
label: currentLabel
});
};
toggleLabel = () => {
this.changeLabel(!this.state.label);
};
render() {
return (
<View>
<Button onPress={this.toggleLabel} title="Toggle Label" />
</View>
);
}
}
Here is another implementation using hooks:
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
export default function App() {
const [label, setLabel] = useState(false);
const toggleLable = () => {
let temp = label;
setLabel(!temp);
};
return (
<View style={styles.container}>
<TouchableOpacity
onPress={toggleLable}
style={[
styles.btn,
{ backgroundColor: label ? '#4f4' : '#f40' },
]}>
<Text style={styles.text}>{label? "TRUE": "FALSE"}</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
btn: {
width: 200,
height: 200,
borderRadius: 20,
justifyContent: "center"
},
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
alignItems: 'center',
},
text:{
fontSize: 40,
fontWeight: "bold",
color: "white",
textAlign: "center"
}
});
Screenshot:
You can play around with the code here: Toggle Button Example
this works for me using useState:
import React, { useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import SeparateModal from 'components/SeparateModal';
export default function Parent() {
const [modalVisible, setModalVisible] = useState(false);
return (
<View>
<SeparateModal
modalVisible={modalVisible}
setModalVisible = {setModalVisible}
/>
<TouchableOpacity>
<Text onPress = { () => setModalVisible(true) }>Open Modal</Text>
</TouchableOpacity>
</View>
)
}
components/SeparateModal:
export default function SeparateModal({ modalVisible, setmodalVisible }) {
return (
<Modal
visible={ modalVisible }
animationType="slide"
>
<View>
<TouchableOpacity>
<Text onPress = { () => setModalVisible(false) }>Close Modal</Text>
</TouchableOpacity>
</View>
</Modal>
);

Resources