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

Latest backend state is not pulled after Supabase login #453

Open
JiiHu opened this issue Jan 28, 2025 · 6 comments
Open

Latest backend state is not pulled after Supabase login #453

JiiHu opened this issue Jan 28, 2025 · 6 comments

Comments

@JiiHu
Copy link

JiiHu commented Jan 28, 2025

I'm creating an app with Expo., with supabase as the backend and authentication service.

I have an issue on existing user logging in, but their data is not pulled from the backend after successful authentication.

Steps to reproduce

  1. Login with supabase
  2. Use Expo app to save data. This data is synced to supabase (checked from their dashboard)
  3. Log out
  4. Restart the app: LegendState is initialised as empty
  5. Log in with the existing user: LegendState doesn't pull the existing data from supabase
  6. Restart the app and LegendState pulls data correctly

I didn't figure out a way to force pull their data from supabase on the step 5. Is there way to manually ask LegendState to fetch whatever backend has?

Here is my integration which is based on LegendState & Supabase documentation. I'm using plan$.get() to render.

utils/SupaLegend.ts

import 'react-native-get-random-values'
import { v4 as uuidv4 } from 'uuid'
import { observable, syncState, when } from '@legendapp/state'
import { syncedSupabase } from '@legendapp/state/sync-plugins/supabase'
import { configureSynced } from '@legendapp/state/sync'
import { observablePersistAsyncStorage } from '@legendapp/state/persist-plugins/async-storage'
import AsyncStorage from '@react-native-async-storage/async-storage'

import { supabase } from '@/utils/supabase'

// Provide a function to generate ids locally
export const generateId = () => uuidv4()

// Create a configured sync function
const customSynced = configureSynced(syncedSupabase, {
  // Use React Native Async Storage
  persist: {
    plugin: observablePersistAsyncStorage({
      AsyncStorage
    })
  },
  generateId,
  supabase,
  changesSince: 'last-sync',
  fieldCreatedAt: 'created_at',
  fieldUpdatedAt: 'updated_at',
  // Optionally enable soft deletes
  fieldDeleted: 'deleted'
})

export const plan$ = observable(
  customSynced({
    supabase,
    collection: 'plan',
    select: from =>
      from.select(
        'id,user_id,type,start_date,end_date,created_at,updated_at,deleted'
      ),
    actions: ['read', 'create', 'update', 'delete'],
    realtime: true,
    persist: {
      name: 'plan',
      retrySync: true
    },
    retry: {
      infinite: true
    }
  })
)
@alterhuman
Copy link

Were you able to fix it?

@JiiHu
Copy link
Author

JiiHu commented Jan 31, 2025

Were you able to fix it?

Not yet. I have hard times figuring out a solution that wouldn't feel like bubblegum fix

@alterhuman
Copy link

alterhuman commented Jan 31, 2025

@jmeistrich facing the same issue, can you please help?

@jmeistrich
Copy link
Contributor

Unless I'm misunderstanding, it sounds like you want the supabase sync to wait until the user is authenticated? Because syncing before auth would get incorrect/invalid data?

So I think you want the waitFor parameter? You you set an isAuthed$ observable to true after being signed in, and use that as the waitFor option.

const customSynced = configureSynced(syncedSupabase, {
  ...,
  waitFor: isAuthed$
})

It's (barely) documented here: https://legendapp.com/open-source/state/v3/sync/crud/#all-options. I think I should expand on the purpose of waitFor as a full section... And maybe there's a way to hook into supabase auth directly to just have a waitForAuth option in the supabase plugin... I'll look into that.

Or am I misunderstanding what you're looking for?

@JiiHu
Copy link
Author

JiiHu commented Feb 3, 2025

Unless I'm misunderstanding, it sounds like you want the supabase sync to wait until the user is authenticated? Because syncing before auth would get incorrect/invalid data?

Yes, this is correct. It would work for me since the user app doesn't have any input to the store before they have to authenticate.

I think adding mention of this to supabase part would also be beneficial, as I assume this is quite common problem.

@juanmigdr
Copy link

juanmigdr commented Feb 15, 2025

I am experiencing the same issue while trying to write to the DB as soon as the user signs in. Before writing to the DB, I check if the record already exists (by ID), and if it does exist, I do not write to the DB. Since I write to the DB before the data has been pulled from it, it is rewriting it. How can I wait until the data has loaded from the DB? I have tried this with and without async storage but no luck

const syncState$ = syncState(state$)
await when(syncState$.isPersistLoaded)
await when(
  () => syncState$.isLoaded.get() && syncState$.isPersistLoaded.get()
);

Thanks in advance ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants