question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Accessing Properties of Linked Objects in ListView RenderRow function throws undefined error

See original GitHub issue

Long winded version is a question on SO, but I am quite certain this is a bug as described in detail farther down this report.

Goal

In the renderRow function to be given as a prop to ListView:

renderRow(item) {
  return (
    <Text>{item.department.name}</Text>
  );
}

Where department is an object property of item

Expected Results

In a row of the ListView, a string of the name property belonging to the department linked to item.

Actual Results

Red Screen of Death Quite a bit of scroll to that screen, can upload more screen captures of it or someone can tell me how to output it to console or a text file.

Steps & Code to Reproduce

You can check out the question on stackoverflow, it was iterated on and has a bit of the flow to it. Below is a more succinct summary of where I believe the bug lays with a basic/partial setup to replicate.

Code Sample

I’ll briefly touch where I think the problem is. This code sample creates console logs that can be seen withadb logcat ReactNative:V ReactNativeJS:V

// Schema Example
class Item {};
Item.schema = {
  name: 'Item',
  primaryKey: 'id',
  properties: {
    id: 'string',
    name: 'string',
    department: 'ItemDepartment',
  }
}

class ItemDepartment {};
ItemDepartment.schema = {
  name: 'ItemDepartment',
  primaryKey: 'id',
  properties: {
    id: 'string',
    name: 'string',
    parentDepartment: 'ItemDepartment'
  }
}

// This truthy test in the if statement allows item.department.name work as intended!
// Check the console log below for a possible lead as for why
getItemDepartmentName(item) {
  let code = item.code;
  console.log("item:      " + item)
  console.log("code:      " + code)
  console.log("typeofX:   " + typeof code)
  if (code) {
    console.log("code True: true")        
    return item.department.name
  }
  console.log("code True: false");
  return "Undefined"
}

renderRow(item) {
  return(
    <Text>{this.getItemDepartmentName(item)}</Text>
  )
}

// for this to work you must bind this on renderRow in listView:
<ListView
  ...
  renderRow={this.renderRow.bind(this)}
.../>

Now, for the console output (Trimmed for readability):

ReactNativeJS: item:      function (row1, row2) {return row1!==row2;}
ReactNativeJS: code:      undefined
ReactNativeJS: typeofX:   undefined
ReactNativeJS: code True: false
ReactNativeJS: item:      function defaultGetRowData(dataBlob, sectionID, rowID) {
ReactNativeJS: return dataBlob[sectionID][rowID];}
ReactNativeJS: code:      undefined
ReactNativeJS: typeofX:   undefined
ReactNativeJS: code True: false
ReactNativeJS: item:      function () {return false;}
ReactNativeJS: code:      undefined
ReactNativeJS: typeofX:   undefined
ReactNativeJS: code True: false
ReactNativeJS: item:      function defaultGetSectionHeaderData(dataBlob, sectionID) {
ReactNativeJS: return dataBlob[sectionID];}
ReactNativeJS: code:      undefined
ReactNativeJS: typeofX:   undefined
ReactNativeJS: code True: false
ReactNativeJS: item:      
ReactNativeJS: code:      undefined
ReactNativeJS: typeofX:   undefined
ReactNativeJS: code True: false
ReactNativeJS: item:      
ReactNativeJS: code:      undefined
ReactNativeJS: typeofX:   undefined
ReactNativeJS: code True: false
ReactNativeJS: item:      
ReactNativeJS: code:      undefined
ReactNativeJS: typeofX:   undefined
ReactNativeJS: code True: false
ReactNativeJS: item:      
ReactNativeJS: code:      undefined
ReactNativeJS: typeofX:   undefined
ReactNativeJS: code True: false
ReactNativeJS: item:      [object RealmObject]
ReactNativeJS: code:      MI1
ReactNativeJS: typeofX:   string
ReactNativeJS: code True: true
ReactNativeJS: item:      [object RealmObject]
ReactNativeJS: code:      MI2
ReactNativeJS: typeofX:   string
ReactNativeJS: code True: true
ReactNativeJS: item:      [object RealmObject]
ReactNativeJS: code:      MI3
ReactNativeJS: typeofX:   string
ReactNativeJS: code True: true

So for some reason (could be my code, but it seems to be hooked up as it should be, pretty standard datasource etc.), ListView starts off calling renderRow with a whole lot of weird inputs, starting with the datasource rowHasChanged function, then what I assume are the Realm.ListView.DataSource default functions. Following that a bunch of calls with what appears to be no argument which obviously has undefined variables. After that it behaves totally normally!

Obviously, if you call item.department.name or the equivalent with any other realm database within the renderRow function, you are gonna to get an error pertaining to undefined. This is due to the strange calling of renderRow with inputs that are not RealmObjects at the start.

Now the weirdest thing about this all is that this doesn’t seem to be a problem with any other properties of the item object: item.name, item.code, even item.department works, successfully returning a RealmObject. As soon as you try to query item.department.name shit hits the fan. I don’t have a hypothesis on that yet. I have my little truthy/falsy fix as above and intend to get on with my work!

Version of Realm and tooling

Realm version(s): 0.11

Android Studio version: Atom/Nuclide latest

Which Android version and device: Only tested on genymotion simulating a nexus 9

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
appdencommented, Apr 13, 2016

@Chris-Petty Thanks for posting this! I noticed from this code that the dataSource is being passed into itself here: dataSource.cloneWithRows(dataSource). This could explain why you’re seeing its own methods being passed into renderRow. Let me know if that helps!

0reactions
appdencommented, Apr 14, 2016

Glad to hear it worked! It’s because the items being passed into renderRow were still objects (functions), so item.code would be undefined but wouldn’t throw an error. However, item.department.name would be trying to access a property on something undefined (item.department).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Linked objects' properties in Realm React-Native ListView ...
I can access each Item string and number properties fine (i.e. item.name). Trying item.department returns a RealmObject, assumedly the one that ...
Read more >
undefined is not an object (evaluating 'this.map.setnativeprops ...
QUESTION ANSWERS. I am having this error while running the app on android. ... not as a single object, so you can display...
Read more >
ListView: Uncaught TypeError: Cannot read property 'apt' of ...
I am trying to start with an initial list of items and display them using the mobile listview. This works fine, however if...
Read more >
Class yii\widgets\ListView
The ListView widget is used to display data from data provider. Each data model is rendered using the view specified. For more details...
Read more >
A deep dive into React Native FlatList - LogRocket Blog
The renderItem function will render the Item component for every item in the array. As a result, this will display the title and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found