realm-js: useQuery data cannot be used directly in FlatList

How frequently does the bug occur?

Always

Description

this returns an empty FlatList:

const {useQuery} = realmContext;

const App = () => {
  const tasklists = useQuery(Tasklist)
  return (
    <FlatList
      data={tasklists}
      keyExtractor={item => String(item._id}
      renderItem={({item, index}) => <Text>index is: {index}</Text>}
    />
  )

❌ does not work

memoizing the useQuery response also returns an empty FlatList:

const {useQuery} = realmContext;

const App = () => {
  const tasklists = useQuery(Tasklist)
  const sorted = useMemo(() => tasklists.sorted(),[tasklists])
  return (
    <FlatList
      data={sorted}
      keyExtractor={item => String(item._id}
      renderItem={({item, index}) => <Text>index is: {index}</Text>}
    />
  )

❌ does not work

spreading the useQuery response to a new array correctly displays the items in the list:

const {useQuery} = realmContext;

const App = () => {
  const tasklists = useQuery(Tasklist)
  return (
    <FlatList
      data={[...tasklists]}
      keyExtractor={item => String(item._id}
      renderItem={({item, index}) => <Text>index is: {index}</Text>}
    />

✅ this works

mapping through the useQuery response renders correctly as well (but without the benefit of the virtualized list).

const {useQuery} = realmContext;

const App = () => {
  const tasklists = useQuery(Tasklist)
  return (
    <View>
      {tasklists.map((tasklist, index) => <Text key={String(tasklist._id)}>index is: {index}</Text>)}
    </View>

✅ this works

the same source code works fine if pasted into the template starter (react-native.todo.flex) which installs react-native 0.70.5, @realm/react 0.4.1, realm 11.2.0

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

No response

Version

realm 11.4.0, @realm/react 0.4.3, react-native 0.71.2

What services are you using?

Atlas Device Sync

Are you using encryption?

Yes

Platform OS and version(s)

IOS and Android

Build environment

realm 11.4.0, @realm/react 0.4.3, react-native 0.71.2

Cocoapods version

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 3
  • Comments: 23 (9 by maintainers)

Most upvoted comments

Another update. React Native 0.71.4 is being put together and will fix the issue. Hopefully will happen soon!

React Native 0.71.4 is out! If you want FlatList support, then I recommend updating to this version.

After discussing this with Meta, they have agreed to loosen the restrictions on the data property to allow for “array-like” structures to be rendered. No current timeline when this will happen, but we are hopeful it will come in a 0.71.x release in the near future. Will keep this open to report and track any progress.

The workaround I’m currently using is patch-package to revert the Array.isArray() guard.


  _getItemCount = (data: ?Array<ItemT>): number => {
    if (data) {
      const numColumns = numColumnsOrDefault(this.props.numColumns);
      return numColumns > 1 ? Math.ceil(data.length / numColumns) : data.length;
    } else {
      return 0;
    }
  };

Moving forward, though, it seems that Realm.Results needs to be updated to pass the data guard inserted with react native 0.71.

The following PRs to react-native will fix this issue: https://github.com/facebook/react-native/pull/36236 (landing in 0.71.x) https://github.com/facebook/react-native/pull/36237 (landing in 0.72.x)

Once these are live, we can close this. Thanks everyone for your patience.

@hadnet Nothing to report right now, we are still in discussions. That being said, it is a priority for us to resolve this, so we will post as soon as we have an update.

Here is the react-native FlatList commit that breaks the useQuery hook:

https://github.com/facebook/react-native/commit/d574ea3526e713eae2c6e20c7a68fa66ff4ad7d2

React native 0.71.3 doesn’t include the changes that meta added. Upgrade to at least 0.71.4

On Jun 22, 2023, at 11:13 AM, lufke wrote: The problem is back again for FlatList, just created an react native app and must use spread operator on data for see the items on list, otherwise it shows an empty list “react": “^0.5.0” “react-native”: “0.71.3” “realm”: “^11.10.1” I can see the items on console.log

Just an update. We are currently in discussions with Meta on how to proceed with this matter. We have two options, either they include a way that we can bypass their check, or we create a Proxy object that wraps an Array and access a Realm collection (with a possible performance regression).

._id is a BSON ObjectId

Using .toHexString() makes no difference.