How to save/download generate QR Code in react native using hooks? - javascript

I'm trying to build an app generator and scanner QR code in react native using hooks. I want a solution to save/download the QR code in the device after generating them. I need help plz, thanks
react-native-qrcode-generator
Can anyone give me suggestions on how to save this generated QR Code? Any help much appreciated

If you want to save the information in QR code as a QR code, you have to convert the QR code into a png image and then store it in your database as an image.
So, what I advise you to do is, when saving, just store the information as a string (or whatever necessary) in the database. When downloading, just retrieve the information from your database and immediately generate the QR Code. It's not consuming a longer time. After the QR Code is generated, then display it.
I think this is the most appropriate solution for you.
You may need react-native-qrcode-generator for generate the QR Code.
Here is a sample code...
You can input key and value (at the top inputs) and press 'Save' button. When the 'Save' button is pressed, you have to store your key-value pair (data) to your database.
Then, input the key (at the bottom input) of which you want to download and press 'Download' button. Then you have to retrieve the data (value) associated with the given key.
State value is set after the value is successfully retrieved from the database. That state is given as a prop to the QRCode component.
import React, { useState } from 'react';
import { StyleSheet, View, Text, TextInput, TouchableOpacity, AsyncStorage } from 'react-native';
import QRCode from 'react-native-qrcode-generator';
export default function App() {
const [key, setKey] = useState(null);
const [value, setValue] = useState(null);
const [downloadKey, setDownloadKey] = useState(null);
const [qrCodeValue, setQRCodeValue] = useState('');
const save = async () => {
//You have to implement the function that saves your information into your database.
//Here I'm saving data to AsyncStorage. (For sample)
await AsyncStorage.setItem(key, value);
}
const download = async () => {
//You have to implement the function that retrieves your information from your database for given key.
//Here I'm retrieving data from AsyncStorage. (For sample)
const qrValue = await AsyncStorage.getItem(downloadKey);
setQRCodeValue(qrValue);
}
return (
<View style={styles.container}>
<View style={styles.row}>
<TextInput placeholder={'Key'} value={key} onChangeText={(key) => setKey(key)} style={styles.textInput}/>
<TextInput placeholder={'Value'} value={value} onChangeText={(value) => setValue(value)} style={styles.textInput}/>
</View>
<TouchableOpacity style={{ flexDirection: 'row', marginBottom: 50 }} onPress={save}>
<Text style={styles.button}>Save</Text>
</TouchableOpacity>
{qrCodeValue ? <QRCode value={qrCodeValue} size={200} /> : null}
<Text style={{ margin: 10 }}>{qrCodeValue}</Text>
<View style={[styles.row, { marginTop: 50 }]}>
<TextInput placeholder={'Key'} value={downloadKey} onChangeText={(downloadKey) => setDownloadKey(downloadKey)} style={styles.textInput}/>
<TouchableOpacity style={{ flex: 1, flexDirection: 'row' }} onPress={download}>
<Text style={styles.button}>Download</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
paddingTop: 50,
paddingBottom: 50
},
row: {
flexDirection: 'row',
},
textInput: {
flex: 1,
borderColor: '#808080',
borderWidth: 1,
borderRadius: 5,
margin: 5,
paddingLeft: 5,
paddingRight: 5,
},
button: {
flex: 1,
borderColor: '#0040FF',
backgroundColor: '#0080FF',
borderWidth: 1,
borderRadius: 5,
margin: 5,
textAlign: 'center',
textAlignVertical: 'center',
height: 30
},
});
Here is a Demo...
Please go through this and feel free to ask me if you have any further problems. Good luck!

You can use rn-qr-generator to generate a QR code with a given string value. It will return a path or base64 representation of the image. Later you can use CameraRoll to save the the image.
import RNQRGenerator from 'rn-qr-generator';
RNQRGenerator.generate({
value: 'string_value',
height: 100,
width: 100,
base64: false,
backgroundColor: 'black',
color: 'white',
})
.then(response => {
const { uri, width, height, base64 } = response;
})
.catch(error => console.log('Error creating QR code image', error));

If you want to save the QR Code as an image to your device, you should convert the QRcode view component into a png image and then store it.
You may use react-native-view-shot to convert the QRcode view component into a png image and rn-fetch-blob to save the image to your gallery.

Related

Cannot display Array in Flatlist format

Long story short, I'm trying to create a list of video-games. I have an autocomplete library that matches a game title with what I write in my input box.
I added a button that onPress triggers a function that pushes what I have in 'query'( which is what I am writing in my input box) into an array called myGamesArray
Then I'm trying to display myGamesArray in list form using Flatlist. But for some reason it is not showing up.
My code is a little messy because the solution I found to place a button next to my input box was by changing the flex direction to 'row'
I added a button right below the FlatList just to check if it would display underneath the inputbox (which it does) but for some reason the flatlist does not
Here's all my App.js
/*This is an example of AutoComplete Input/ AutoSuggestion Input*/
import React, { Component } from 'react';
//import react in our code.
import { StyleSheet, Text, TouchableOpacity, View, Image, Alert, FlatList } from 'react-native';
//import all the components we are going to use.
import Autocomplete from 'react-native-autocomplete-input';
import { Button, List, Container, ListItem, Header } from 'native-base';
//import Autocomplete component
//Demo base API to get the data for the Autocomplete suggestion
class App extends Component {
constructor(props) {
super(props);
//Initialization of state
//games will contain the array of suggestion
//query will have the input from the autocomplete input
this.state = {
myGamesArray: [],
games: [],
query: '',
};
}
componentDidMount() {
//First method to be called after components mount
//fetch the data from the server for the suggestion
fetch('https://api.rawg.io/api/games?page=1&platforms=18', {
"method": "GET",
"headers": {
"x-rapidapi-host": "rawg-video-games-database.p.rapidapi.com",
"x-rapidapi-key": "495a18eab9msh50938d62f12fc40p1a3b83jsnac8ffeb4469f"
}
})
.then(res => res.json())
.then(json => {
const { results: games } = json;
this.setState({ games });
//setting the data in the games state
});
}
findGame(query) {
//method called everytime when we change the value of the input
if (query === '') {
//if the query is null then return blank
return [];
}
const { games } = this.state;
//making a case insensitive regular expression to get similar value from the game json
const regex = new RegExp(`${query.trim()}`, 'i');
//return the filtered game array according the query from the input
return games.filter(game => game.name.search(regex) >= 0);
}
AddItemsToArray=()=>{
//Adding Items To Array.
this.state.myGamesArray.push( this.state.query.toString() )
// Showing the complete Array on Screen Using Alert (just to check if it's infact inside the array)
Alert.alert(this.state.myGamesArray.toString());
}
render() {
const { query } = this.state;
const games = this.findGame(query);
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
return (
<View>
<View style={styles.container}>
<Autocomplete
style={styles.autocompleteContainer1}
autoCapitalize="none"
autoCorrect={false}
//data to show in suggestion
data={games.length === 1 && comp(query, games[0].name) ? [] : games}
//default value if you want to set something in input
defaultValue={query}
/*onchange of the text changing the state of the query which will trigger
the findGame method to show the suggestions*/
onChangeText={text => this.setState({ query: text })}
placeholder="Selecione os jogos que voce quer receber!"
renderItem={({ item }) => (
//you can change the view you want to show in suggestion from here
//I GET ERROR WHEN TRYING TO ERASE (PS4) IN TEXT BOX ***NEED TO CHECK THIS
<View style={styles.iconContainer} >
<TouchableOpacity onPress={() => this.setState({ query: item.name})}
style={styles.itemContainer} >
<View>
<Image
style={styles.profilepic}
source={{uri: item.background_image}}
/>
</View>
<Text style={styles.itemText}>
{item.name} (PS4)
</Text>
</TouchableOpacity>
</View>
)}
/>
<Button
style={styles.addButton}
icon='plus'
title="Click Here To Add Value To Array"
onPress={() => this.AddItemsToArray()}
/>
<View style={styles.descriptionContainer}>
{games.length > 0 ? (
//Text inside input box
<Text style={styles.infoText}>{this.state.query}</Text>
) : (
<Text style={styles.infoText}>{this.state.query}</Text>
)
}
</View>
</View>
<View style={styles.container2}>
<Button
full></Button>
<FlatList
data={this.state.myGamesArray}
renderItem={({ item }) => (
<ListItem>{item}</ListItem>
)}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
flex: 1,
flexDirection:'row',
padding: 16,
marginTop: 40,
justifyContent: 'center',
},
container2: {
backgroundColor: '#fff',
flex: 1,
marginTop: 100,
alignItems: 'center',
justifyContent: 'center',
},
autocompleteContainer1: {
borderWidth: 1,
backgroundColor: "#fff",
borderColor: '#7843FF',
height: 50,
width:300
},
itemContainer: {
flex:1,
flexDirection: 'row',
borderWidth:0.5,
borderColor: '#7843FF',
paddingVertical: 5,
alignItems: 'center',
paddingRight: 60
},
addButton: {
width:50,
height: 50,
borderColor: '#7843FF',
borderWidth: 0.5,
backgroundColor: '#fff'
},
descriptionContainer: {
flex: 1,
justifyContent: 'center',
borderRadius: 10,
color: '#fff',
borderColor: '#7843FF'
},
itemText: {
fontSize: 15,
marginLeft: 10,
marginRight:30,
marginVertical:10,
color: '#000',
textAlign: 'left',
justifyContent: 'center'
},
infoText: {
textAlign: 'center',
color: '#000',
},
profilepic: {
flex: 3,
height: 60,
width: 60,
marginLeft:10,
borderRadius: 100,
},
});
export default App;
Issue
this.state.myGamesArray.push(this.state.query.toString()) is a state mutation. You need to actually do a state update and return a new array object reference.
Solution
Use a functional state update to access the previous state object, and shallow copy the old array into a new array reference and append the new query value to the end.
Also, logging or otherwise trying to reference the updated state right after enqueueing the update won't work like that, state is const and updated between render cycles so it'll enclose the current state.
AddItemsToArray = () => {
//Adding Items To Array.
this.setState(prevState => {
const { myGamesArray, query } = prevState;
return {
myGamesArray: [...myGamesArray, query.toString()],
};
},
// Use setState callback to alert with the updated state
() => {
// Showing the complete Array on Screen Using Alert (just to check if it's in fact inside the array)
Alert.alert(this.state.myGamesArray.toString());
},
);
}

(firebase error) set failed first argument contains undefined in property [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
My add button gives me this error when I click it, but it still adds the input text to my firebase.
How do i get rid of this error?
import React, { Component } from 'react';
import { View, Text, StyleSheet, Button, TextInput, TouchableOpacity, ScrollView } from 'react-native';
import firebase from './firebase';
export default class App extends Component {
carDatabase = firebase.database().ref('car');
state = { cars: {}, selectedId: '', text: ''}
// Read
componentDidMount() {
this.carDatabase.on('value', cars => {
const carsJSON = cars.val();
this.setState({ cars: carsJSON === null ? {} : carsJSON });
})
// this.carDatabase.push({color: 'yellow'})
}
// Create
create() {
this.carDatabase.push('space') /// changes selected item
this.setState({selectedId: ''})
}
add() {
this.carDatabase.push(this.state.text).set(TextInput.value) /// pushes textput to firebase
this.setState(TextInput.value)
}
// Update
update() {
this.carDatabase.child(this.state.selectedId).set('space') /// changes text of selected item
this.setState({selectedId: ''})
}
// Delete
deleteCar() {
if(this.state.selectedId === '') { ///selects item
return;
}
this.carDatabase.child(this.state.selectedId).set(null) ///deletes item
this.setState({selectedId: ''})
}
render() {
return (
<View style={styles.container}>
<ScrollView>
<Text style={styles.top}>Todo List</Text>
<TextInput value={this.state.text} style={styles.textInput}></TextInput>
<Button title="create" onPress={() => this.create()}></Button>
<Button title="update" onPress={() => this.update()}></Button>
<Button title="delete" onPress={() => this.deleteCar()}></Button>
<Button title="add" onPress={() => this.add()}></Button>
{
Object.keys(this.state.cars).map( (carId, index, text) =>
<TouchableOpacity key={index} onPress={() => this.setState({ selectedId: carId, text})}>
<Text style={styles.input}>{`${JSON.stringify(this.state.cars[carId])}`} </Text>
</TouchableOpacity>
)
}
<TextInput ///creates text input
style={{height: 40}}
placeholder="Type here to add"
onChangeText={(text) => this.setState({text})}
value={this.state.text} ///gets text input
/>
<Text style={{padding: 10, fontSize: 42}}> {this.state.text.value} </Text>
</ScrollView>
{/* <Text>{JSON.stringify(this.state.cars, null, 2)}</Text> */}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
width: '100%'
},
textInput: {
backgroundColor: '#ADD8E6',
height: 40,
width: '100%'
},
input: {
backgroundColor: '#ADD8E6',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
top: {
backgroundColor: 'white',
height: 45,
paddingLeft: 140,
paddingTop: 20,
fontSize: 20,
alignItems: 'center',
justifyContent: 'center'
}
});
From the way you describe it, this is the call that is causing problems:
this.carDatabase.push(this.state.text).set(TextInput.value)
Since you say the database is still updated, it seems the push(...) works, but the set(...) is failing. As the error message says, that would be caused by TextInput.value being undefined.
If that is indeed the case, log the value of TextInput.value before you write it to the database and verify that it is what you expect it to be.
If the above is not the cause, then honesty it's too hard to determine exactly where the problem is coming from in what you've current shared. I'd recommend reducing the scope of your question and the code. Read how to create a minimal, complete, verifiable example to learn why and how to do that, is it will drastically increase the chances that someone may help and will also often reduce the downvotes that your question attracts.

How to save/download generate QRCode inn react native

By using this code I am able to generate QRCode but , I don't know how to save that qrcode in png/jpeg format ono long press or automatic .
I need some help or idea to solve that .. I tried few examples but not getting success . I am keep trying.
import React, { Component } from 'react';
//import react in our code.
import { StyleSheet, View, TextInput, TouchableOpacity, Text,} from 'react-native';
// import all basic components
import QRCode from 'react-native-qrcode-svg';
//import QRCode
class App extends Component {
svg;
constructor() {
super();
this.state = {
inputValue: '',
inputValue2: '',
// Default Value of the TextInput
valueForQRCode: '',
// Default value for the QR Code
};
}
getTextInputValue = () => {
// Function to get the value from input
// and Setting the value to the QRCode
this.setState({ valueForQRCode: this.state.inputValue + this.state.inputValue2 });
};
shareQR =() =>{
this.svg.toDataURL((data) => {
const shareImageBase64 = {
title: "QR",
message: "Ehi, this is my QR code",
url: `data:image/png;base64,${data}`
};
Share.open(shareImageBase64);
});
}
render() {
return (
<View style={styles.MainContainer}>
<QRCode
value={"Abhigyan" + this.state.valueForQRCode}
//Setting the value of QRCode
size={250}
//Size of QRCode
bgColor="#000"
//Backgroun Color of QRCode
fgColor="#fff"
//Front Color of QRCode
getRef={(ref) => (this.svg = ref)}
onPress={() =>{shareQR()}}
/>
<TextInput
// Input to get the value to set on QRCode
style={styles.TextInputStyle}
onChangeText={text => this.setState({ inputValue: text })}
underlineColorAndroid="transparent"
placeholder="Enter text to Generate QR Code"
/>
<TextInput
// Input to get the value to set on QRCode
style={styles.TextInputStyle}
onChangeText={text => this.setState({ inputValue2: text })}
underlineColorAndroid="transparent"
placeholder="Enter text to Generate QR Code"
/>
<TouchableOpacity
onPress={this.getTextInputValue}
activeOpacity={0.7}
style={styles.button}>
<Text style={styles.TextStyle}> Generate QR Code </Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button}onPress={this.shareQR}>
<Text style={styles.buttonText}>Share</Text>
</TouchableOpacity>
</View>
);
}
}
export default App;
const styles = StyleSheet.create({
MainContainer: {
flex: 1,
margin: 10,
alignItems: 'center',
paddingTop: 40,
},
TextInputStyle: {
width: '100%',
height: 40,
marginTop: 20,
borderWidth: 1,
textAlign: 'center',
},
button: {
width: '100%',
paddingTop: 8,
marginTop: 10,
paddingBottom: 8,
backgroundColor: '#F44336',
marginBottom: 20,
},
TextStyle: {
color: '#fff',
textAlign: 'center',
fontSize: 18,
},
});
//Thanks .
// In QRCode I am able to generate and QRCode scanner both I have done ,but how to download /save or share that qrcode ,Please help
This answer refers to react-native-qrcode-svg library, as written in the question comments.
With this library you can create an svg to show the QR you want and then access it by reference. So, create a reference in your component:
class App extends Component {
svg;
constructor() {
...
};
}
...
}
Assign it the QRCode, for example:
<QRCode
value={"Abhigyan" +this.state.valueForQRCode}
size={250}
color="#fff"
getRef={(ref?) => (this.svg = ref)}
/>
Now you can access its content with this.svg.toDataURL(//callback).
Example: you wanna share the QR as an image/png using react-native-share by clicking on a button which calls this function:
shareQR() {
this.svg.toDataURL((data) => {
const shareImageBase64 = {
title: "QR",
message: "Ehi, this is my QR code",
url: `data:image/png;base64,${data}`
};
Share.open(shareImageBase64);
});
}
This is just an example, if you prefer to use react-native-fs you can refer to the example given in the official repository.
Update to support onPress function
You're trying to pass onPress prop to QRCode, but QRCode does not support it. Instead, wrap it in a TouchableOpacity:
<TouchableOpacity onPress={this.shareQR}>
<QRCode
value={"Abhigyan" +this.state.valueForQRCode}
size={250}
color="#fff"
getRef={(ref?) => (this.svg = ref)}
/>
</TouchableOpacity>
You can use react-native-view-shot to create an image of QR code then you can save it in camera roll or disk storage.

React Native: Can't style the Button

I am quite new to React Native. I am familiar with React and use it for my work. React Native seems different in terms of applying styles to the components.
I am having issue applying styles to the button.
Here is my current code:
<Button
title="LET'S GET STARTED"
onPress={() => {
console.log('You tapped the Decrypt button!');
}}
buttonStyle={{
backgroundColor: "#0A6ABB",
width: 300,
height: 45,
borderColor: "#FFFFFF",
borderWidth: 2,
borderRadius: 5
}}
containerStyle={{ marginTop: 50 }}
/>
I tried multiple ways, but the styles are not being applied the button that I have created.
Here is the screenshot of how it looks like:
"Let's get started" is the button and no matter what it just has the default blue text.
How can I fix this?
Could anyone please help me with this?
Is your Button component imported from react-native? If yes then you can't style it because as stated on their documentation, below are the supported props, buttonStyle is not supported prop. Alternatively, maybe you can try other packages like Button from react-native-elements or NativeBase
onPress
title
accessibilityLabel
color
disabled
testID
hasTVPreferredFocus
Button is very limited in react native. You can use TouchableOpacity instead to give you more flexibility See documentation here.
TouchableOpacity example:
render () {
return (
<TouchableOpacity
style={styles.button}
onPress={this.onPress} >
<Text> LETS GET STARTED </Text>
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10
},
});
There are also different kinds of "buttons" depending on what you need like TouchableHighlight, TouchableWithoutFeedback
Use TouchableOpacity
import { StyleSheet, TouchableOpacity, Text }
render() {
return (
<TouchableOpacity
style={styles.button}
onPress={() => { console.log('You tapped the Decrypt button!'); }}
>
<Text> LET'S GET STARTED </Text>
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: "#0A6ABB",
width: 300,
height: 45,
borderColor: "#FFFFFF",
borderWidth: 2,
borderRadius: 5,
marginTop: 50
},
});

Missing primary key property in Realm

The error I'm getting says Missing primary key property 'email'. I'm completely new to databases and would like to know what the issue is with my code.
Also, am I writing to the database correctly? If I were to successfully place items into the database, how would I be then able to view it?
I've looked around SO and Google for this, but can't to find a concrete answer.
error I'm getting
Here's .js file:
import React, { Component } from 'react';
import {TextInput, KeyboardAvoidingView, Text, StyleSheet, TouchableOpacity} from 'react-native';
import Third from './Third';
class Second extends Component {
onButtonPress() {
this.props.navigator.push({
id: 'Third' // .js file name
});
}
render() {
const Realm = require('realm');
class Email {}
Email.schema = {
name: 'Email',
primaryKey: 'email',
properties: {
name: 'string',
},
};
const realm = new Realm({schema: [Email]});
// Query
let email = realm.objects('Email');
// email.length // => 0
// Write
realm.write(() => {
email = realm.create('Email', {
name: 'something',
});
});
return(
<KeyboardAvoidingView style={styles.container}>
<TextInput
style={styles.userInput}
placeholder={" email"}
/>
<TextInput
style={styles.userInput}
placeholder={" password"}
secureTextEntry={true}
/>
<TouchableOpacity style={styles.buttonContainer}>
<Text onPress={this.onButtonPress.bind(this)} style={styles.buttonText}>Submit</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20 // makes button horizontally longer.
},
userInput: {
marginBottom: 20,
height: 40,
borderWidth: 4
},
userInput: {
marginBottom: 20,
backgroundColor: '#9b42f4',
height: 40,
borderRadius: 10,
borderWidth: 1
},
buttonContainer: {
backgroundColor: '#41bbf4',
paddingVertical: 10,
marginBottom: 20,
borderRadius: 10
},
buttonText: {
textAlign: 'center',
color: '#FFFFFF'
}
});
export default Second;
The error is because you have email as the primary key in your schema, which become a required property when you create an Email object. Did you mean to have name as the primary key instead of email? Or something like an id property.
One way to get rid of this error is to replace email in your primaryKey setting with name.
For viewing you data, you can use https://github.com/realm/realm-browser-osx, but it is only available on Mac OS right now.
P.S. when you make schema changes, you would want to delete the app and reinstall it. It is fine for now if you are just start developing it.
Later on, you should increase the schema version instead and write migrations after you have you app in the store. (Maybe even start before that)

Categories

Resources