React Native Realm Migration - react-native

In React Native, where are you supposed to put the migration code or code to delete the realm database (ignoring migration) and for it to only run once?
I tried deleting the Realm database each time I am back on the Login screen. When I try to login, it is supposed to save the user info into Realm and then the app proceeds as normal. However this is not the case, it seems because Realm database was deleted, it has no where to save it. I would have thought that once I login, by saving the user info into Realm, it would initialize Realm and then save the user in Realm.
In debug mode, it seems even by deleting the Realm database, everything functions normally. Debug mode is a lot slower, so is there a timing issue somewhere?
Is there a method to initialize Realm?

This is what I did to get the migration to work.
I have realm.js located in /src where I keep all my react files. When I need to use my realm I import realm from 'path/to/realm.js';
In realm.js I have my old schema and my new schema.
import Realm from 'realm';
const schema = {
name: 'mySchema',
properties: {
name: 'string',
}
};
const schemaV1 = {
name: 'mySchema',
properties: {
name: 'string',
otherName: 'string',
}
};
Note they have the same name. Then at the bottom of my realm.js where I used to have export default new Realm({schema: [schema]});
I now have this:
export default new Realm({
schema: [schemaV1],
schemaVersion: 1,
migration: (oldRealm, newRealm) => {
// only apply this change if upgrading to schemaVersion 1
if (oldRealm.schemaVersion < 1) {
const oldObjects = oldRealm.objects('schema');
const newObjects = newRealm.objects('schema');
// loop through all objects and set the name property in the new schema
for (let i = 0; i < oldObjects.length; i++) {
newObjects[i].otherName = 'otherName';
}
}
},
});
If you don't need to migrate the data, you could just open the Realm with the new schema version and new schema and it should also work.

If you have just added or removed fields of your schema, you can performe a empty migration. This is my realm.js file:
import Realm from 'realm';
//models
import Registros from '../models/registros';
import Local from '../models/local';
export default function getRealm() {
return Realm.open({
schema: [Registros, Local],
schemaVersion: 1, //add a version number
migration: (oldRealm, newRealm) => {
},
});
}

Related

WebSQL threw an error [Error: Error code 1: no such table: document-store]

We are using react-naive-sqlite-2 in our application with RxDB and started getting this error somewhat sporadically. It seems to happen after we remove the database. I was surprised to see this was a WebSQL error since we are using react-native and WebSQL is deprecated. I don't have great ways to debug this but my hunch is that we have some code that still tries to access the now dead database.
This is the code we use to set up our database:
import SQLiteAdapterFactory from 'pouchdb-adapter-react-native-sqlite'
import SQLite from 'react-native-sqlite-2'
import { addRxPlugin, createRxDatabase } from 'rxdb'
import { RxDBReplicationGraphQLPlugin } from 'rxdb/plugins/replication-graphql'
import type { DatabaseType } from '../generated'
/**
* SQLITE SETUP
*/
const SQLiteAdapter = SQLiteAdapterFactory(SQLite)
addRxPlugin(SQLiteAdapter)
addRxPlugin(require('pouchdb-adapter-http'))
/**
* Other plugins
*/
addRxPlugin(RxDBReplicationGraphQLPlugin)
export const getRxDB = async () => {
return await createRxDatabase<DatabaseType>({
name: 'gatherdatabase',
adapter: 'react-native-sqlite', // the name of your adapter
multiInstance: false,
})
The issue happens after we logout and attempt to log back in. When we logout, we call removeRxDatabase. Has anyone ran into this kind of issue before or know of ways to debug?
For posterity, the issue was that we had a reference to the database in our state management library (Zustand) that was being held onto past logout. When we tried to login again, our getOrCreateDatabase function didn't make a new one but it wasn't valid since we had run database.remove() in rxdb. We ended up just clearing the Zustand db and calling database.remove() at one place.
export const useRxDB = create<UseRxDBType>((set, get) => ({
database: undefined,
/**
* we set the database to ready in the LocalDocument store once local docs are loaded into the store
*/
databaseIsReady: false,
getOrCreateDatabase: async () => {
let database = get().database
if (!database) {
database = await createRxDatabase()
if (!Rx.isRxDatabase(database)) throw new Error(`database isnt a valid RxDB database.`)
set({ database })
}
return database
},
resetDatabase: async () => {
const database = get().database
if (database) {
await database.remove()
set({ database: undefined })
}
},
}))

realm migration issue on android

I am trying to run multiple migrations on clean React Native android app.
But i get this error. The code works on iOS though.
"Unable to open a realm at path '.management'"
My schemas:
schemas = [
{ schema: [Order, Settings] },
{ schema: [Order, Settings], schemaVersion: 1, migration: schemaVersion1Migration }
];
let nextSchemaIndex = Realm.schemaVersion(Realm.defaultPath);
while (nextSchemaIndex < schemas.length) {
const migratedRealm = new Realm(schemas[nextSchemaIndex++]);
migratedRealm.close();
}
Realm.open(schemas[schemas.length-1])
Used try catch block to catch the exeception and continue on install.

Multiple realms in React Native don't query realm object server correctly on first launch of app after install

I am having an issue dealing with multiple realms in React Native. I'm working on an app that allows users to use the app without having a subscription (using a local realm) and then at any point in their app journey they have the option of upgrading to a subscription with syncing (which uses sync to a realm object server).
When I start the app I check to see if they are using sync and if so I initialize a synced realm with their user and everything works great. I get all the data I expect.
However, when the app starts on first launch after install (that part about first launch after install is crucial) and I see that they don't use sync I initialize a local realm which I save data to until they decide to log in to their sync account (if they have one). At this point I attempt to pull information from the synced realm but it does not have the information that I saw when I only initialized the synced realm (in the case that on app startup I detect they use sync).
I am able to log in as the sync user but the data isn't there if I've previously initialized a local realm AND this logic gets run on the first launch of the app after install. The data only shows up from the realm object server when I initialize a local and synced realm on a secondary launch of the app (no reinstall before launching).
Here's a simple test script with dummy data in it with which I've been able to replicate the observed behavior:
const username = 'testuser2';
const password = 'supersecret';
const tld = 'REALM_OBJECT_SERVER_TLD';
class Test extends Realm.Object {}
Test.schema = {
name: 'Test',
properties: {
id: {
type: 'string',
},
}
};
function initLocalRealm() {
return new Realm({
path: 'local.realm',
schema: [Test],
});
}
function initSyncedRealmWithUser(user) {
return new Realm({
path: 'synced.realm',
sync: {
user,
url: `realm://${tld}:9080/~/data`,
},
schema: [Test],
});
}
function writeTestObjectWithId(realm, id) {
realm.write(() => {
realm.create('Test', {
id,
});
alert(`Test object with id: ${id}`);
});
}
initLocalRealm();
// setup
// uncomment this and comment out the login section to setup user on first run
// Realm.Sync.User.register(`http://${tld}:9080`, username, password, (error, user) => {
// if (error) {
// return;
// }
// const syncedRealm = initSyncedRealmWithUser(user);
// writeTestObjectWithId(syncedRealm, '1');
// });
// login
Realm.Sync.User.login(`http://${tld}:9080`, username, password, (error, user) => {
if (error) {
return;
}
const syncedRealm = initSyncedRealmWithUser(user);
alert(`Synced realm test objects: ${syncedRealm.objects('Test').length}`);
});
If you create a react native app and then add this code to the main components componentDidMount function you should see that on the first run of the app (after you've uncommented the register code once) you will see the Test collection length at 0, but then when you refresh you will see the Test collection length at 1.
Any help on this would be awesome.
Thanks!
running your code snippet, I get a length of 1 immediately as soon as I uncomment the login section. Could you try observing your synchronized realm with the Realm Browser and see if it seems to have the data you are expecting after registering the user?

Object type 'ShortAnswer' not found in schema in Realm React Native

My schema defination in file realmDB.js :
'use strict';
var Realm = require('realm');
class ShortAnswer extends Realm.Object{}
ShortAnswer.schema = {
name: 'ShortAnswer',
properties: {
question: 'string',
answer: 'string'
}
};
export default new Realm({schema: [ShortAnswer]});
In my short_answer.js file,
I include the realmDB by using import realm from './realmDB';.
Here,
realm.write(() => {
realm.create('ShortAnswer',{
question: this.state.short_question,
answer: this.state.short_answer
});
});
I am new in realm and react native.
The input for the question and answer is taken from two respective TextInput. But when i give input and press the save button to save question and answer into the database, the error Object type 'ShortAnswer' not found in schema. occurs. What can be done to solve this problem ?
I had a similar error message and problem. Turns out I need to do a better job of reading the realm documentation. In my case I had multiple Realms, on for Contacts and another for Auth data. The Auth data realm was created more recently and was overwriting the Contacts realm. To solve this problem I needed to add a path to the realm creation like so:
export default new Realm({path: 'somePath.realm', schema: [ShortAnswer]});
Afterwards everything worked fine.
This should work. The only thing I see different from mine is that you are inheriting from Realm.Object. Have you tried just doing this?
class ShortAnswer {}

GraphQL schema won't import

I'm trying setup an express GraphQL server. Following a tutorial when I put the following in the server startup like this:
// ENTIRE SCHEMA IN MAIN FILE THIS WORKS!!!
...
var graphql = require('graphql');
const RootQuery = new graphql.GraphQLObjectType({
name: 'RootQuery',
description: 'The root query',
fields: {
viewer: {
type: graphql.GraphQLString,
resolve() {
return 'viewer!';
}
}
}
});
const Schema = new graphql.GraphQLSchema({
query: RootQuery
});
app.use('/graphql', graphqlHTTP({ schema: Schema }));
...
it works, returning the data 'viewer! But as I don't want everything in the main file, I tried to transfer this exact code to another file and import it like this:
//THIS DOES NOT WORK
...
var Schema = require('./build/models/graphql/schema');
app.use('/graphql', graphqlHTTP({ schema: Schema }));
...
I get the following error:
{
"errors": [
{
"message": "Schema must be an instance of GraphQLSchema. Also ensure that there are not multiple versions of GraphQL installed in your node_modules directory."
}
]
}
I'm not sure what I'm doing wrong. In case this has anything to do with it, I am writing in es6 then transpiling back to 5 in a build script. Here's the build of the schema file:
// TRANSPILED SCHEMA
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var graphql = require('graphql');
var RootQuery = new graphql.GraphQLObjectType({
name: 'RootQuery',
description: 'The root query',
fields: {
viewer: {
type: graphql.GraphQLString,
resolve: function resolve() {
return 'viewer!';
}
}
}
});
var Schema = new graphql.GraphQLSchema({
query: RootQuery
});
exports.default = Schema;
And here is my package.json:
"express": "^4.13.4",
"express-graphql": "^0.5.3",
"graphql": "^0.6.0",
I've checked that only one graphql is in the node_modules folder. Does graphql expect the same INSTANCE across all modules, like a shared global instance? Does express-graphql use it's own version? How do I check? I'm new to node, is there a way to check the instances?
I don't think this is a GraphQL problem, but a problem with how you're using require and exports in JS. The problem is probably:
var Schema = require('./build/models/graphql/schema')
along with
var Schema = new graphql.GraphQLSchema({
query: RootQuery
});
exports.default = Schema;
You're not importing the same value that you're exporting. Try either exporting Schema as module.exports = Schema or importing it as Schema = require("./...").default
Also ensure that there are not multiple versions of GraphQL installed in your node_modules directory.
As the error indicates, this most likely has to do with more than one copy of GraphQL in your node_modules directory. Have you checked that? If there is more than one copy, you might be able to solve it by running npm dedupe if you're using npm version 2. If you're using npm 3, then most likely you've installed two different versions of the graphql module.
Either way, you have to make sure that after the compile step, express-graphql and your schema both point to the same copy of the graphql module.
If you think implementing & maintaining Graphql services (mainly their schemas), please have a look at graphqly. Here's a sample code to define Graphql schemas:
import graphly from "graphqly";
const gBuilder = graphly.createBuilder();
// define types, inputs ... (in any order)
gBuilder.type("Products").implements("List").def(`
products: [Product]!
`);
gBuilder.type("Product").def(`
id: ID!
name: String!
link: String
price: Int
`);
// we're too lazy to define a separate input, so we can `extend` other structure
gBuilder.input("ProductInput").ext("Product");
gBuilder.enum("ProductOrder").def(`
PRICE_DESCENDING
PRICE_ASCENDING
NEWEST
`);