facebook / relay

Relay is a JavaScript framework for building data-driven React applications.
https://relay.dev
MIT License
18.4k stars 1.82k forks source link

Hooks - `useFragment` (sometimes) returns null when record is deleted #3514

Open davidgovea opened 3 years ago

davidgovea commented 3 years ago

Version: react-relay@11.0.2

Issue: the return value for useFragment is null in some circumstances. The types suggest that this should not occur.

Repro in the example TODO app: https://codesandbox.io/s/usefragment-returns-null-6tynl?file=/src/Todo.tsx:1027-1035

https://user-images.githubusercontent.com/489896/121592515-c8106980-ca08-11eb-89fb-ecff932b9fe9.mp4

Notes:

Using @deleteEdge (or the corresponding updater code, as is in the example TODO app) works fine. However, in our use case, the record also needs to be deleted in order to update other bits of UI.

Other approaches tried:

Thanks for reading!

ianplatt555 commented 3 years ago

Version: v12.0.0

Has there been any progress on this issue? I'm currently having the same problem I believe. Essentially ComponentA renders an array of ComponentB where each component B has a useFragment. ComponentB can send a mutation to delete itself with @deleteRecord but then the app crashes because upon re-render, ComponentB still renders and useFragment returns null.

georgekaran commented 2 years ago

Did you guys manage to solve this issue? I'm facing the exact same problem, my useFragment returns a null value when I use a @deleteRecord directive.

daniloab commented 2 years ago

why should not return null if is being deleted?

josephsavona commented 2 years ago

Thanks for reporting, what's happening here is that when a record is deleted in the store, sometimes a child component (eg rendering the item) can update before the parent. If the parent updates first, it would un-render the child. But if the child updates first, the data is null.

Relay supports injecting a scheduler which allows opting-in to using React's batched updates, which ensure that the parent will update first and avoid this issue. We should update Relay to make this behavior the default for new environments. For now, you can work around this by passing the following as the scheduler when creating an environment:

const RelayScheduler: TaskScheduler = {
  cancel: () => {},
  schedule: task => {
    React.unstable_batchedUpdates(task);
    return '';
  },
};

new Environment({
   ..., // network, store, etc
   scheduler: RelayScheduler,
});
casperstr commented 1 year ago

Im still getting this error on relay 14 using React Native. I have tried using unstable_batchedUpdates from react-native but the error persists.

PedroBern commented 1 year ago

Im still getting this error on relay 14 using React Native. I have tried using unstable_batchedUpdates from react-native but the error persists.

Same here, on relay 15 and react native 0.71.3

import { unstable_batchedUpdates } from 'react-native'

Didn't work.