Nozbe / WatermelonDB

🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️
https://watermelondb.dev
MIT License
10.49k stars 589 forks source link

withObservables with a received array #1175

Open tbveloso opened 3 years ago

tbveloso commented 3 years ago

Hi,

I'm enhancing a component using this code:

const enhance = compose(
  withObservables(['user'], ({user}) => ({
    user,
    students: user.students,
  })),

  withObservables(['studentProfile'], ({students}) => {
    const studentProfile = students.map(student => student.studentProfile.observe());

    return {
      s0: studentProfile[0],
      s1: studentProfile[1],
      ...,
    };
  }),
);

I'm showing this way for easy understanding... but i'm using js reduce to create the observables properties to Component...

I wonder if there's a better way to handle array when using withObsevables...

Thanks...

KrisLau commented 3 years ago

I think this one can be done with https://rxjs-dev.firebaseapp.com/api/index/function/from but I'm not entirely sure since I'm still learning to use RxJS myself

tbveloso commented 3 years ago

i tried many ways and I always getting an observable object on Component....

Object
    asObservable: ƒ ()
    closed: false
    complete: ƒ ()
    constructor: ƒ ()
    destination: Object
    error: ƒ ()
    forEach: ƒ ()
    hasError: false
    isStopped: false
    lift: ƒ ()
    next: ƒ ()
    observers: Array(0)
    operator: Object
    pipe: ƒ ()
    source: Object
    subscribe: ƒ ()
    thrownError: null
    toPromise: ƒ ()
    unsubscribe: ƒ ()
    _isScalar: false
    _subscribe: ƒ ()
    _trySubscribe: ƒ ()
    __proto__: Object

i have this relation on User Model:

@relation('profiles', 'user_id') studentProfile

it's necessary subscribe() this object, using useEffect to get the db raw values...

But when I put the Observable object directly on withObservables return, I get the raw values...

  withObservables(['studentProfile'], ({students}) => {
    const studentProfile = students.map(student => student.studentProfile.observe());

    return {
      s0: studentProfile[0],
      s1: studentProfile[1],
      ...,
    };
  }),

@KrisLau I tried from$, but after subscribe() the object, i got only 1 item from array... I resolved this point using of$, but its necessary to run subscribe() anyway using useEffect...

i would like receive the raw values directly from the component properties...

i tried this other approach...:

const enhance = withObservables(
  ['user'],
  ({user}) => {
    return {
      user,
      students: user. students.observe().pipe(
        map$(userStudents => {
          return userStudents.map(us => {
            const {userId, isAccepted, ..., studentProfile} = us;
            return {
              id: userId,
              isAccepted,
              ...,
              profile: studentProfile.observe(),
            };
          });
        }),
      ),
    };
  },
);

...but receiving the Observable object on Component property...

:(

KrisLau commented 2 years ago

Sorry for taking so long to reply but you're trying to use compose and withObservables to create a component right? If so, it should look something like this:

const enhancedComponent = compose (
  withObservables(['user'], ({user}) => ({
    user, //equivalent to something like database.get('user').query().observe()
  })),
)(Component)

The problem with yours is probably somewhere in your studentProfile observable. I'm not exactly sure what is wrong but I would suggest checking to see if user and student are being queried correctly to start with. Then, maybe doing a studentProfile query in your component first before trying to do it in a withObservable. https://nozbe.github.io/WatermelonDB/Components.html#reactive-relations