Missing primary key property in Realm - javascript

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)

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());
},
);
}

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

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.

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 white screen

I'm new on React-Native, really Im new on React. Im doing the exercises from Learning-React-Native.'s book. But there are a lot of things that are differents, I think for version. My code shows a white screen on the ADV and suppose it must show another thing. Console doesn't show any error.
Book suggests in Forecast.js file, render: function(){...} but it launch me an error on this way for that reason I change it just by render() {...}
This is my WeatherProject.js
// Importing react Components module
import React, { Component } from 'react';
// Importing another modules for React.
import {
Platform,
StyleSheet,
Text,
TextInput,
View
} from 'react-native';
import Forecast from './Forecast';
/*
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
*/
// WeatherProject class for WeatherProject.js
export default class WeatherProject extends Component {
// App exec always as first the constructor method
constructor(props){
/*
* La palabra clave super se usa para acceder y llamar funciones en el elemento primario de un objeto.
* The super keyword can also be used to call functions on a parent object.
* The parent class is Component.
*
* super([arguments]); // calls the parent constructor.
* super.functionOnParent([arguments]);
*
*/
super(props);
// Constructor controls the first state of variables that can be modified by this keyword.
this.state = {
zip: '',
forecast: {
main: 'Clouds',
description: 'few clouds',
temp: 45.7
}
}
}
// _handleTextChange method use a event for change a value of zip variable with this.setState
_handleTextChange(event) {
console.log(event.nativeEvent.text);
// Getting the event value and setting on zip variable
this.setState({
zip: event.nativeEvent.text
});
}
// Render de application.
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
You input {this.state.zip}.
</Text>
<Forecast
main={this.state.forecast.main}
description={this.state.forecast.description}
temp={this.state.forecast.temp}/>
<TextInput
style={styles.input}
returnKeyType='go'
onSubmitEditing={this._handleTextChange}/>
</View>
);
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
input: {
fontSize: 20,
borderWidth: 2,
height: 40,
},
});
This is my Forecast.js
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View
} from 'react-native';
class Forecast extends Component {
render() {
return (
<View>
<Text style={styles.bigText}>
{this.props.name}
</Text>
<Text style={styles.mainText}>
Current conditions: {this.props.description}
</Text>
<Text style={styles.bigText}>
{this.props.temp}°F
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
bigText: {
flex: 2,
fontSize: 20,
textAlign: 'center',
margin: 10,
color: "#FFF"
},
mainText: {
flex: 1,
fontSize: 16,
textAlign: 'center',
color: "#FFF"
}
});
module.exports = Forecast;
There isn't any error here. Your text is same color with screen so you can't see it. Just change text color in your Forecast
const styles = StyleSheet.create({
bigText: {
flex: 2,
fontSize: 20,
textAlign: 'center',
margin: 10,
color: "black" // Change it to black
},
mainText: {
flex: 1,
fontSize: 16,
textAlign: 'center',
color: "black" // Change it to black
}
});
A white screen means a fatal error and the entire app has crashed. Sometimes it can be the smallest littlest hardest bug to find, such as const userID = user.uid and user is undefined so the app crashes and can go white. I recommend integrating bugsnag as they have a free tier and will help you figure out where the errors are occurring.

Attempting to create an object of type with an existing primary key value 'not implemented'

I'm trying to store user email address in Realm whenever the user hits Submit but whenever I do so, I'm getting the error (link below). I understand that data persists in realm and every time I render, I'm trying to create a new Email object with the same name.
I followed https://realm.io/docs/javascript/latest/#updating-objects (the update section). Maybe updating will do the trick to fix this issue? realm.write() method is what I'm focusing on.
error I'm getting
Here's my .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: 'name',
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'
});
realm.create('Email', {name: "else"}, true);
});
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;

Categories

Resources