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

useQuery is not reactive #391

Open
alisman opened this issue Aug 16, 2022 · 3 comments
Open

useQuery is not reactive #391

alisman opened this issue Aug 16, 2022 · 3 comments
Assignees
Labels
Discussion enhancement New feature or request
Projects
Milestone

Comments

@alisman
Copy link

alisman commented Aug 16, 2022

**Let start by saying thank you. This library looks amazing, well documented, and I really want to use it. But I don't get this one bit.

Suppose I have a paginated list of TODO items. The page number I am currently displaying is a piece of local application state which, as I understand it, should be kept in a property of the app store (add using properties method of the base store type. If I mutate that page number, any component that references it will re-render accordingly in the normal Mobx-React way. However, as others have noted, useQuery, which fetches the set of TODO items to display will NOT re-fire (as it would with an old fashioned fetch inside useEffect). So, effectively the data is NOT reactive.

Apparently the idiomatic way to solve this problem in mst-qgl is by using setQuery in callback to pagination clicks and passing it the return of an action that loads items and returns a new query object. When I call that action, i need to pass the new page number. Great! Except that I now need to update the page number state inside an action with the name "loadItems", which is doable, but makes no sense.

When I click a page number, the conceptual action I am firing is that I am setting the page number state. Everything else is a computation of that state. I am not loading data. If data needs to load because I have changed the local state, that should be handled reactively. The component which references page number should re-render and the userQuery inside should detect that a dependency has changed and it needs to refetch data.

So,

  1. I don't get why useQuery does not behave like useEffect in re-firing when its deps change
  2. I don't understand this setQuery. It seems to require that I call these "load" actions all over the place in order to get hold of the new query.

Can anyone (@mweststrate) explain the reason it works this way?

@mweststrate
Copy link
Member

mweststrate commented Aug 16, 2022 via email

@alisman
Copy link
Author

alisman commented Aug 16, 2022

@jamonholmgren could you comment on this?

@Benz19 Benz19 added this to the v0.19.0 milestone Nov 4, 2022
@jesse-savary jesse-savary added this to To do in Overhaul DX via automation Nov 6, 2022
@jesse-savary jesse-savary added the enhancement New feature or request label Nov 6, 2022
@Wishez
Copy link

Wishez commented Jul 26, 2023

I'm afraid I can't. I only worked a couple of weeks on this project three and half years ago, so I'm afraid I don't have any context anymore 😅.

I possibly have a same case and can provide a simplified context

In my app, i have two components ComponentA and ComponentB that use user data. They're rendered on a same page and both use same query for getting user data

It's first component that uses user data and it's not rendered if user aren't authenticated

const ComponentA = observer(() => {
   const { data, loading, store } = useQuery((store: RootStoreType) => store.queryCurrentUser({}), { fetchPolicy: 'cache-only' })
   const user = data?.currentUser
   if (!user) return null

   return `${user.firstName} ${user.lastName}`
})

It's second component. It has user data and the login button. When users click on the login button, then they get a token, the app sets a token to the httpClient of RootStore, and it refetches an user with query.refetch() from the local useQuery. This component render user data after refetching, but component above doesn't

const ComponentB = observer(() => {
   const { data, loading, store, query } = useQuery((store: RootStoreType) => store.queryCurrentUser({}))
   const user = data?.currentUser

  return (
    <>
      {user && <p>{user.firstName} {user.lastName}</p>}

      <button
        type="button"
        onClick={() => {
           const token = await getTokenSomeWay() // it's declared somewhere and give us an user token
           store.gqlHttpClient.setHeaders({ Authorization: `Bearer ${token}` })
           query?.refetch()
        }}
      >
        Login
      </button>
    </>
  )
})

I assume it's not reactive behavior of useQuery

I expected ComponentA will get updated user data too. How can i share data of the one query between components?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Discussion enhancement New feature or request
Projects
Development

No branches or pull requests

5 participants