Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fail to create / push an object with linkingObjects to its parent #1475

Closed
adrianchancy opened this issue Nov 7, 2017 · 16 comments
Closed

Comments

@adrianchancy
Copy link

Questions: In another project, I can use linkingObjects well. But I don't know why I cannot create or push object with linkingObjects to its parent for now. Once I create or push object linkingObjects to its parent, the UI freezes and the app cannot run. I force quit the app and reenter it. The UI still freezes and the app cannot run.

Please help.

Expected Results

It can update / create the object

Actual Results

It cannot update / create the object. The UI freezes even after force quit and reopen the app. And the app cannot run.

Steps to Reproduce

  1. Run the below code
  2. tap "Click me."

Code Sample

I modified a bit of your example to simulate my case and I got the same result.

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';

const Realm = require('realm');

const CarSchema = {
  name: 'Car',
  properties: {
    make: 'string',
    model: 'string',
    miles: { type: 'int', default: 0 },
    owners: { type: 'linkingObjects', objectType: 'Person', property: 'cars' } // What I added
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name: 'string',
    birthday: 'date',
    cars: 'Car[]',
    picture: 'data?'
  }
};

export default class App extends Component {

  Update = () => {
    Realm.open({ schema: [CarSchema, PersonSchema] })
      .then(realm => {
        realm.write(() => {
          const myCar = realm.create('Car', {
            make: 'Honda',
            model: 'Civic',
            miles: 1000,
          });
          myCar.miles += 20;
        });

        const cars = realm.objects('Car').filtered('miles > 1000');

        realm.write(() => {
          const myCar = realm.create('Person', {
            name: 'Adrian',
            birthday: new Date(),
            cars: [{
              make: 'BMW',
              model: '8310',
              miles: 200
            }]
          });
        });
        alert(JSON.stringify(realm.objects('Car')))
      });
  }

  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', }}>
        <Text onPress={() => this.Update()} style={{ alignSelf: 'center' }}>
          Click me.
        </Text>
      </View>
    );
  }
}

Version of Realm and Tooling

  • Realm JS SDK Version: 2.0.3
  • React Native: 0.50.1
  • Client OS & Version: Android 7.0, iOS 11 (Both simulator and real device)
  • Which debugger for React Native: Google Chrome (It happens even without debugger)
@kneth
Copy link
Contributor

kneth commented Nov 8, 2017

And you don't observe it when you remove owners? Does it also freeze if the BWM is created separately and added to Adrian's cars as a Realm object?

@adrianchancy
Copy link
Author

I rewrite the code in the following way, by separating the creation of Car and Person. And then link them together. It does not freeze after trigger the linkage, but neither Car and Person object shows their linkage after refresh.

Once I click "Link Car to Person", a yellow warning message is prompted.

"Possible Unhandled Promise Rejection (id: 1): Error: properties must be of type 'object', got (undefined)" ==> Why so? Please help

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';

const Realm = require('realm');

const CarSchema = {
  name: 'Car',
  properties: {
    make: 'string',
    model: 'string',
    miles: { type: 'int', default: 0 },
    owners: { type: 'linkingObjects', objectType: 'Person', property: 'cars' }
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name: 'string',
    birthday: 'date',
    cars: 'Car[]',
    picture: 'data?'
  }
};

export default class App extends Component {

  state = {
    cars: null,
    people: null
  }

  createPerson = () => {
    Realm.open({ schema: [CarSchema, PersonSchema] })
      .then(realm => {
        const myCar = realm.objects('Car')[0]
        realm.write(() => {
          realm.create('Person', {
            name: 'Adrian',
            birthday: new Date(),
            picture: null
          });
        })
      })
  }

  createCar = () => {
    Realm.open({ schema: [CarSchema, PersonSchema] })
      .then(realm => {
        realm.write(() => {
          realm.create('Car', {
            make: 'Honda',
            model: 'Civic',
            miles: 1000,
          });
        })
      })
  }

  linkCarToPerson = () => {
    Realm.open({ schema: [CarSchema, PersonSchema] })
      .then(realm => {
        const myPerson = realm.create('Person')[0]
        const myCar = realm.create('Car')[0]
        realm.write(() => {
          myPerson.cars.push(myCar)
        })
      })
  }

  componentWillMount() {
    Realm.open({ schema: [CarSchema, PersonSchema] })
      .then(realm => {
        this.setState({
          cars: realm.objects('Car')[0],
          people: realm.objects('Person')[0],
        })
      })
  }

  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', }}>
        <Text onPress={() => this.createCar()} style={{ alignSelf: 'center' }}>
          Create a Car
        </Text>
        <Text onPress={() => this.createPerson()} style={{ alignSelf: 'center', marginTop: 20 }}>
          Create a Person
        </Text>
        <Text onPress={() => this.linkCarToPerson()} style={{ alignSelf: 'center', marginTop: 20 }}>
          Link Car to Person
        </Text>
        <Text style={{ alignSelf: 'center', marginTop: 20 }}>
          Cars: {JSON.stringify(this.state.cars)}
        </Text>
        <Text style={{ alignSelf: 'center', marginTop: 20 }}>
          People: {JSON.stringify(this.state.people)}
        </Text>
      </View>
    );
  }
}


@kneth
Copy link
Contributor

kneth commented Nov 9, 2017

realm.create('Person')[0] will create a new object. I think you really mean realm.object('Person')[0].

@adrianchancy
Copy link
Author

Thanks, it should be realm.create('Person')[0].

But when I tried with the amended code, the objects cannot yet linked together.
I refreshed and see that both class become null

@adrianchancy
Copy link
Author

By the way, I tried below using the version 1.13.0 and 2.0.5 respectively.
The former runs well, but the latter has problem.
After I reload the page, I got a blank page.

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';

const Realm = require('realm');



const CarSchema = {
  name: 'Car',
  properties: {
    make: 'string',
    model: 'string',
    miles: { type: 'int', default: 0 },
    owners: { type: 'linkingObjects', objectType: 'Person', property: 'cars' }
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name: 'string',
    birthday: 'date',
    cars: {type: 'list', objectType: 'Car'},
    picture: 'string'
  }
};

var realm = new Realm({schema: [CarSchema, PersonSchema], schemaVersion: 0 })

export default class App extends Component {

  state = {
    cars: null,
    people: null
  }

  createPerson = () => {
    realm.write(() => {
      realm.create('Person', {
        name: 'Adrian',
        birthday: new Date(),
        picture: "Hello"
      }
      )
    })
  }

  createCar = () => {
    realm.write(() => {
      realm.create('Car', {
        make: 'Honda',
        model: 'Civic',
        miles: 1000,
      })
    })
  }

  linkCarToPerson = () => {

    const myPerson = realm.objects('Person')[0]
    const myCar = realm.objects('Car')[0]
    try {
      realm.write(() => {
        myPerson.cars.push(myCar)
      })
    } catch (e) {
      alert(e);
    }
  }

  showCarOwner = () => {
    
        const myCar = realm.objects('Car')[0]
        alert(JSON.stringify(myCar.owners))
      }

  componentWillMount() {
    this.setState({
      cars: realm.objects('Car') ? realm.objects('Car'): null,
      people: realm.objects('Person')? realm.objects('Person'): null,
    })
  }

  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', }}>
        <Text onPress={() => this.createCar()} style={{ alignSelf: 'center' }}>
          Create a Car
        </Text>
        <Text onPress={() => this.createPerson()} style={{ alignSelf: 'center', marginTop: 20 }}>
          Create a Person
        </Text>
        <Text onPress={() => this.linkCarToPerson()} style={{ alignSelf: 'center', marginTop: 20 }}>
          Link Car to Person
        </Text>
        <Text onPress={() => this.showCarOwner()} style={{ alignSelf: 'center', marginTop: 20 }}>
          Show the Car own
        </Text>
        <Text style={{ alignSelf: 'center', marginTop: 20 }}>
          Cars: {JSON.stringify(this.state.cars)}
        </Text>
        <Text style={{ alignSelf: 'center', marginTop: 20 }}>
          People: {JSON.stringify(this.state.people)}
        </Text>
      </View>
    );
  }
}


@kneth
Copy link
Contributor

kneth commented Nov 10, 2017

When you have a few minutes, it would be great if you tried to rewrite cars: {type: 'list', objectType: 'Car'} as cars: Car[]. It will only work for 2.0.x.

@esutton
Copy link

esutton commented Nov 10, 2017

@kneth Did the schema format change from 2.0.x? Are changes documented somewhere?

Are you saying this is no longer valid schema ?

 cars: {type: 'list', objectType: 'Car'},

@kneth
Copy link
Contributor

kneth commented Nov 10, 2017

@esutton The old one should work but cars: Car[] is the new one way. From 2.0.0, you can also have names: string[] so you don't have to create a wrapper for primitive types like numbers and strings 😄.

@adrianchancy
Copy link
Author

@kneth

I love the shorthand and also the array of primitive type a lot.
2.0 is wonderful to me.

But as I cannot use 2.0.x, I cannot enjoy the new features.

@kneth
Copy link
Contributor

kneth commented Nov 15, 2017

@adrianchancy Please take a look at https://github.com/realm/realm-js/blob/master/tests/js/linkingobjects-tests.js and see if you are using Realm in a different way. If you are, I will be happy if you can contribute a test to expose any bugs.

@kneth kneth closed this as completed Mar 5, 2018
@JohnBra
Copy link

JohnBra commented May 13, 2019

I have the same problem. I think it might have to do with the .push method ... App screen freezes after push execution of linked object.

My schema:

class Log extends Realm.Object {}
Log.schema = {
    name: 'Log',
    properties: {
        date: 'date',
        elapsedSeconds: 'int',
        belongsTo: {type: 'linkingObjects', objectType: 'Activity', property: 'logs'}
    }
};

class Activity extends Realm.Object {}
Activity.schema = {
    name: 'Activity',
    primaryKey: 'id',
    properties: {
        id: {type: 'int', indexed: true},
        label: 'string',
        color: 'Color',
        logs: 'Log[]',
    }
};

Creation of a log object in the realm (works), fetching an activity from the realm(works):

realm.write(() => {
  let newLog = realm.create('Log', {date: new Date(), elapsedSeconds: elapsedSeconds});
  let editActivity = realm.objectForPrimaryKey('Activity', currentActivity.id);
  editActivity.logs.push(newLog); // <- this breaks it
});

If i rewrite the Activity schema property logs from logs: Log[] to logs: {type: 'list', objectType: 'Log'} it does not break anymore, but the logs entry of the Activity is empty after the push is executed.

Question on the side .. is there a special reason, why lists are objects of objects {0:{...}, 1:{...}} rather than arrays of objects [{...},{...}] ?

kneth added a commit that referenced this issue May 14, 2019
@kneth
Copy link
Contributor

kneth commented May 14, 2019

@JohnBra In #2370 I have added a test which is inspired by your code snippet. On node.js it does not fail.

Question on the side .. is there a special reason, why lists are objects of objects {0:{...}, 1:{...}} rather than arrays of objects [{...},{...}] ?

The reason is that the objects are not plain JS objects but "managed" objects. That is, a collection is not an array but an object which has most of the behaviour of an array.

@JohnBra
Copy link

JohnBra commented May 14, 2019

@kneth thank you for the quick reply!

I have just tested it on a clean react-native app with not additional libs and code ... sadly it shows the same behaviour. Tested on device (Android 6) and emulator (iOS, iPhone X 12.2).

Steps to reproduce

  1. react-native init RealmTest
  2. cd RealmTest
  3. yarn add realm
  4. react-native link realm
  5. insert code below into App.js
  6. react-native run-ios or react-native run-android
  7. click on 'Click to add items to Realm' in the App

This is the code i used:

import React, {Component} from 'react';
import {StyleSheet, Text, View, TouchableHighlight} from 'react-native';

const Realm = require('realm');

const ColorSchema = {
  name: 'Color',
  primaryKey: 'id',
  properties: {
    id: {type: 'int', indexed: true},
    value: 'string'
  }
};


const LogSchema = {
  name: 'Log',
  properties: {
    date: 'date',
    elapsedSeconds: 'int',
    belongsTo: {type: 'linkingObjects', objectType: 'Activity', property: 'logs'}
  }
};

const ActivitySchema = {
  name: 'Activity',
  primaryKey: 'id',
  properties: {
    id: {type: 'int', indexed: true},
    label: 'string',
    color: 'Color',
    logs: 'Log[]'
  }
};

type Props = {};
export default class App extends Component<Props> {
  constructor(props) {
    super(props);
    this.state = { realm: null };
  }

  addItemsToRealm() {
    Realm.clearTestState();
    Realm.open({
      schema: [ActivitySchema, LogSchema, ColorSchema]
    }).then(realm => {
      realm.write(() => {
        let color = realm.create('Color', {id: 1, value: '#f00'});
        let activity = realm.create('Activity', {id: 1, label: 'Tmp Activity', color: color, logs:[]});

        // create log separately and then push
        //let log = realm.create('Log', {date: new Date(), elapsedSeconds: 42});
        //activity.logs.push(log);

        // create log in push command (best for my usecase)
        activity.logs.push({date: new Date(), elapsedSeconds: 42});

        // create activity after log including log in array (doesn't fit my usecase) also breaks
        //let activity = realm.create('Activity', {id: 1, label: 'Tmp Activity', color: color, logs:[log]});

        let getAllActivities = realm.objects('Activity');

        console.warn(getAllActivities);
      });
      this.setState({ realm });
    });
  }

  render() {
    const info = this.state.realm
        ? 'Number of Activities in this Realm: ' + this.state.realm.objects('Activity').length
        : 'Loading...';

    return (
        <View style={styles.container}>
          <TouchableHighlight onPress={() => this.addItemsToRealm()}>
            <Text>Click to add items to Realm</Text>
          </TouchableHighlight>
          <Text style={styles.welcome}>
            {info}
          </Text>
        </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  }
});

I have included a few different ways to add a log to the activity object (see commented lines). None of those work.

@JohnBra
Copy link

JohnBra commented May 14, 2019

I'd be happy to lend a you a hand testing on react-native @kneth

@adrianchancy
Copy link
Author

adrianchancy commented May 14, 2019

I guess that is something related to the object we got.
The issue is also discussed in #1532

@JohnBra
Copy link

JohnBra commented May 14, 2019

@adrianchancy thanks for the help! It seems to be this exact problem ... in my applications it still breaks for both cases (remote debugging on and off)

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants