realm migration issue on android - react-native

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.

Related

React Native IAP getSubscriptions returns empty array for iOS

I am following this library to implement In App Purchase for react native project.
Project info:-
inside package.json
"dependencies": {
"react": "16.11.0",
"react-native": "0.61.5",
"react-native-iap": "^4.4.9"
},
And I am trying to get product list,
import * as RNIap from 'react-native-iap';
const itemSkus = Platform.select({
ios: [
'com.cooni.point1000',
'com.cooni.point5000', // dooboolab
],
android: [
'com.example.coins100'
]
});
try {
const result = await RNIap.initConnection();
await RNIap.consumeAllItemsAndroid();
console.log('result', result);
if(result == true){
console.log("itemSkus>>>", itemSkus)
const products = await RNIap.getSubscriptions(itemSkus);
console.log("getting_products>>>", products)
this.setState({ products });
}
} catch(err) {
console.warn(err); // standardized err.code and err.message available
}
I am getting true for initConnection but getting [] (empty array) for getSubscriptions and also for getProducts()
By the way, I am getting empty array also for project which is in testFlight for using subscription ids that I have created. Those are in "Waiting for review state"
Is it not possible to get result using above test iap ids and ids that are in "Waiting for review state"?
How can I get response either using example or real ids?
Any help should be appreciable.
These are the possible solutions please check
The products are not in the 'Ready To Submit' state (make sure you've added the screenshot).
You haven't signed your Paid Applications Agreement in App Store Connect
You're testing on an emulator instead of a physical device.
My experience with RN-IAP for iOS was that it is super-unreliable, and plagued with issues where it works differently from documentation, and differently from Android version. The best solution I found was to switch to RevenueCat service for purchase management - that works great, after about an year of use I have not encountered any issues or differences between Android and iOS.
I was having the same problem and found that it worked if I removed the bundle ID from iOS product ID.
const itemSkus = Platform.select({
ios: [
'point1000',
'point5000', // dooboolab
],
android: [
'com.example.coins100'
]
});

Unable to include AB Testing for React Native application

I am integrating A/B Testing for my React Native application using Firebase. I have tried two methods - using react-native-ab and react-native-ab-test.
In the first case, I get an error saying "undefined is not an object(evaluating PropTypes.string)"
In the second case, I get an error saying "index.ios.js tries to require 'react-native' but there are several files providing this module. You can delete or fix them."
In both the cases, I get these errors just by importing the dependency in my JS file. By seeing the github pages of both dependencies, I think there is no need to link both the dependencies and they run fine.
Links :
https://github.com/lwansbrough/react-native-ab
https://github.com/landaio/react-native-ab-test
I installed it with this module and it works perfectly, you can try this:
https://github.com/invertase/react-native-firebase
https://rnfirebase.io/docs/v5.x.x/getting-started
and then it is to configure the remote config so that the a-b test works for you
https://rnfirebase.io/docs/v5.x.x/config/reference/config
I'm using A/B testing and works for me with this module:
"react-native-firebase": "3.3.1",
and needs pod too.
pod 'Firebase/Core', '~> 5.11.0'
pod 'Firebase/RemoteConfig', '~> 5.11.0'
My logic
import firebase from 'react-native-firebase';
setRemoteConfigDefaults() {
if (__DEV__) {
firebase.config().enableDeveloperMode();
}
// Set default values
firebase.config().setDefaults({
my_variant_remote_config_param: ''
});
}
/**
* FIREBASE remote config fetch
* #param valueToFetch: remote config key
*/
export const fetchRemoteConfig = async (valueToFetch: RemoteConfigKeysTypes): Promise<string> => {
try {
await firebase.config().fetch();
await firebase.config().activateFetched();
const snapshot = await firebase.config().getValue(valueToFetch);
const response = snapshot.val();
return response;
} catch (error) {
firebase.analytics().logEvent('remote_config_get_value_error', { error, key: valueToFetch });
return null;
}
};
More Info:
https://www.npmjs.com/package/react-native-firebase

React Native Realm Migration

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

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?

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
`);