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
}
});
Related
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>
I have a very simple question. I am using hooks, and in the docs there is an example given to change the text using hooks. But there is place where I am not able to figure it out.
Below is my code:
import React, { useState } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
const HelloWorldApp = () => {
const [textUpdate, setText] = useState('text1');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>{textUpdate}</Text>
<Text>{todos.text}</Text>
</View>
);
}
export default HelloWorldApp;
I can see text1 on the screen, But I cant see Learn hooks on the screen. What is wrong with <Text>{todos.text}</Text> ??
EDIT
So I changed <Text>{todos.text}</Text> to <Text>{todos[0].text}</Text>.
Now I wanted to change the text on the click.
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>{textUpdate}</Text>
<Text>{todos[0].text}</Text>
<TouchableOpacity onPress={changeText} >
<Text>Click me</Text>
</TouchableOpacity>
</View>
and also added changeText in the component.
const changeText = () => {
if (textUpdate === 'text1' || todos[0].text === 'Learn') {
setText('text2');
setTodos({ text: 'done' })
} else if (textUpdate === 'text2' || todos[0].text === 'done') {
setText('text1');
setTodos({ text: 'Learn' })
}
}
It gives an error undefined is not an object (evaluating 'todos[0].text')
UPDATED ISSUE
You have initialized state an array of object and reset it like object only
UPDATED SOLUTION
Try using as an array of an object like
const changeText = () => {
if (textUpdate === 'text1' || todos[0].text === 'Learn') {
setText('text2');
setTodos([{ text: 'done' }]) // add like array
} else if (textUpdate === 'text2' || todos[0].text === 'done') {
setText('text1');
setTodos([{ text: 'Learn' }]) // add like array
}
}
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>
);
I have a webview source that I have opened using react-native-webview, I want to access any and every url and console it whenever I click on the webview, so that I can use it as source for another webview. However am unable to figure how to do it
I tried using NavigationStateChange and onShouldLoadSTartwithrequest but that did not help.
below is my code
import React, {useState, useRef, useEffect} from 'react';
import {WebView} from 'react-native-webview';
import {
View,
SafeAreaView,
ActivityIndicator,
StyleSheet,
TouchableOpacity,
Text,
Linking,
Alert,
BackHandler,
} from 'react-native';
import Footer from '../components/Footer';
import {useBackHandler} from '#react-native-community/hooks';
import OnlineConsultationWebviewScreen from './OnlineConsultationWebviewScreen';
export default function ConsultationHomeScreen(props) {
const uri = props.route.params.uri;
const [canGoBack, setCanGoBack] = useState(false);
const [canGoForward, setCanGoForward] = useState(false);
const [currentUrl, setCurrentUrl] = useState('');
const webviewRef = useRef(null);
const renderLoadingView = () => {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<ActivityIndicator size="large" />
</View>
);
};
const onMessage = (e) => {
// retrieve event data
var data = e.nativeEvent.data;
// maybe parse stringified JSON
try {
data = JSON.parse(data);
} catch (e) {}
// check if this message concerns us
if ('object' == typeof data && data.external_url_open) {
// proceed with URL open request
return Alert.alert(
'External URL',
'Do you want to open this URL in your browser?',
[
{text: 'Cancel', style: 'cancel'},
{text: 'OK', onPress: () => Linking.openURL(data.external_url_open)},
],
{cancelable: false},
);
}
};
const jsCode = `!function(){var e=function(e,n,t){if(n=n.replace(/^on/g,""),"addEventListener"in window)e.addEventListener(n,t,!1);else if("attachEvent"in window)e.attachEvent("on"+n,t);else{var o=e["on"+n];e["on"+n]=o?function(e){o(e),t(e)}:t}return e},n=document.querySelectorAll("a[href]");if(n)for(var t in n)n.hasOwnProperty(t)&&e(n[t],"onclick",function(e){new RegExp("^https?://"+location.host,"gi").test(this.href)||(e.preventDefault(),window.postMessage(JSON.stringify({external_url_open:this.href})))})}();`;
return (
<SafeAreaView style={{flex: 1}}>
<WebView
source={{
uri: uri,
}}
renderLoading={renderLoadingView}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={true}
ref={webviewRef}
injectedJavaScript={jsCode}
onMessage={onMessage}
onError={console.error.bind(console, 'error')}
// onShouldStartLoadWithRequest={(event) => {
// if (event.url !== uri ){
// Linking.openURL(event.url);
// console.log('Event', event.url);
// return false;
// }
// return true;
// }}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
tabBarContainer: {
padding: 20,
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: '#b43757',
},
button: {
color: 'white',
fontSize: 24,
},
});
Am stuck with this since long, please let me know how do I access any and every click and console it, so that I can sue it later as a new source for Webview.
Any suggestion would be great.
Try this :
<WebView
ref="webview"
source={uri}
onNavigationStateChange={this._onNavigationStateChange.bind(this)}
javaScriptEnabled = {true}
domStorageEnabled = {true}
injectedJavaScript = {this.state.cookie}
startInLoadingState={false}
/>
Add this function :
_onNavigationStateChange(webViewState){
console.log(webViewState.url)
}
FYI webviewState object consists of, use the url property:
{
canGoBack: bool,
canGoForward: bool,
loading: bool,
target: number,
title: string,
url: string,
}
let me know if it helps
So I'm doing something fairly simple in with react-native. I have a function that creates a copy of the state which is initially an array, I then update the copy and then I would eventually call my setState in order to update the original array. However, when I mutate the copy, for some odd reason it also mutates the array from the state even if I don't call setState. I tried everything that I thought might fix it, using slice, [...copy], splicing it, nothing, it still mutates, and why, I just don't understand why it mutates? If anyone can help me that would be really appreciated.
Here is the function
function completeTaskHandler(goalName, taskId, taskIndex, updateAction) {
const taskSnapShot = tasks.slice();
console.log(taskSnapShot);//logs the copy
console.log(tasks);// logs the original array
taskSnapShot[taskIndex].isComplete = "true";
console.log(taskSnapShot);//results in mutated array
console.log(tasks);//Also results in mutated array why??
};
Here is the full Code block
import React, { useState } from "react";
import { View, StyleSheet, TouchableOpacity } from "react-native";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import { useSelector, useDispatch } from "react-redux";
import { Ionicons } from "#expo/vector-icons";
//Custom Components
import Task from "../../components/local/goals/EditGoalTask";
//Header Custom Component
import CustomBackButton from "../../components/HeaderButtonDark";
//Controllers
import { DefaultText, SmallText, HeaderText, SmallTextItalic } from "../../controllers/TextController";
//Constants
import Colors from "../../constants/Colors";
//Redux reducers
import { udpateTask } from "../../store/actions/user";
const EditGoal = ({ navigation, route }) => {
//Initialize variables
const dispatch = useDispatch();
const { goalId, goalNameFromAddPage } = route.params;
let selectedGoal = useSelector(state => state.userReducer.goals.find((goal) => goal.id === goalId));
if (goalNameFromAddPage) {
selectedGoal = useSelector(state => state.userReducer.goals.find((goal) => goal.goalName === goalNameFromAddPage));
}
//Deconstruct needed variables
const { goalName, startDate, status, tasksArrayOfObjects } = selectedGoal;
//Initialize States
const [tasks, setTasks]= useState(tasksArrayOfObjects.fitler((task) => {
if (!task.isComplete) {
return true;
} else {
return false;
}
}));
//Methods
function deleteTaskHandler(goalName, taskId, taskIndex, updateAction) {
const taskSnapShot = [...tasks];
taskSnapShot.splice(taskIndex, 1);
setTasks(taskSnapShot);
//dispatch(udpateTask(goalName, taskId, updateAction));
};
/* Has issues */
function completeTaskHandler(goalName, taskId, taskIndex, updateAction) {
const taskSnapShot = tasks.slice();
console.log(taskSnapShot);
console.log(tasks);
taskSnapShot[taskIndex].isComplete = "true";
console.log(taskSnapShot);
console.log(tasks);
/*
function copyArray(arr) {
const arrCopy = arr.slice();
const copy = arrCopy.splice(0, arrCopy.length);
return copy;
}
console.log(tasks);
const taskSnapShot = copyArray(tasks);
taskSnapShot[taskIndex].isComplete = true;
console.log(taskSnapShot);
console.log(tasks);
*/
//dispatch(udpateTask(goalName, taskId, updateAction));
};
navigation.setOptions({
headerLeft: () => (
<HeaderButtons HeaderButtonComponent={CustomBackButton}>
<Item
title="BACK"
iconName="md-close"
onPress={() => navigation.popToTop()}
/>
</HeaderButtons>
),
});
return(
<View style={styles.screen}>
<View style={styles.header}>
<View style={styles.goalContainer}>
<SmallText>Goal:</SmallText>
<HeaderText>{goalName}</HeaderText>
</View>
<View style={styles.goalStatusContainer}>
<SmallText style={styles.headerTextMargin}>Started: {startDate}</SmallText>
<View style={{ flexDirection: "row" }}>
<SmallText>Finished: </SmallText>
<SmallTextItalic>{status}</SmallTextItalic>
</View>
</View>
</View>
<View style={styles.pageDescription}>
<DefaultText>
Here is where you can add, delete, or track the steps you need to do in
order to achieve your goal.
</DefaultText>
</View>
<View style={styles.taskContainer}>
{tasks.map((task, index) => {
return <Task
title={task.taskName}
key={"key"+index}
deleteTask={deleteTaskHandler.bind(this, goalName, task.id, index, "delete")}
completeTask={completeTaskHandler.bind(this, goalName, task.id, index, "complete")}
/>
})}
<View style={styles.touchableContainer}>
<TouchableOpacity onPress={() => alert()}>
<View style={{...styles.task, ...styles.addAStepContainer}}>
<View style={styles.addAStep}>
<Ionicons style={{ marginRight: 5 }} name="ios-add" size={23} color={Colors.grey} />
<DefaultText style={{ color: Colors.grey, fontSize: 18 }}>Add a step</DefaultText>
</View>
</View>
</TouchableOpacity>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
screen: {
paddingHorizontal: 10,
},
header: {
flexDirection: "row",
height: 80,
//alignItems: 'center',
},
pageDescription: {
paddingVertical: 10,
},
goalContainer: {
flex: 1,
},
goalStatusContainer: {
flex: 1,
alignItems: "flex-end",
},
headerTextMargin: {
marginBottom: 4,
},
touchableContainer: {
borderRadius: 10,
overflow: "hidden",
},
taskContainer: {
//borderWidth: 1,
},
addAStepContainer: {
paddingVertical: 20,
},
addAStep: {
flexDirection: "row",
},
});
export default EditGoal;
This is a little bit tricky. When you do:
const taskSnapShot = tasks.slice();
you create a new array, but inside that array, you won't duplicate the objects from tasks but just make a reference to these objects. So basically, taskSnapShot is an array of references. So when you modify an object inside taskSnapShot, you also modify it in tasks.
To solve this problem you have to duplicate the object that you want to modify:
const taskSnapShot = [...tasks];
taskSnapShot[taskIndex] = {...taskSnapShot[taskIndex], isComplete: true};