mst-gql icon indicating copy to clipboard operation
mst-gql copied to clipboard

Refetch query after variables changes

Open mtsewrs opened this issue 5 years ago • 25 comments

I'm currently using mst-gql with next.js and cannot get it to refetch queries when variable from the route changes, has anyone had problems with this before? The component rerenders but it does not refetch the query.

mtsewrs avatar Feb 04 '20 16:02 mtsewrs

I'm about to start using this with next.js so I'll let you know how it goes for me or if I run into anything.

chrisdrackett avatar Feb 06 '20 21:02 chrisdrackett

@mattiasewers I've been bitten by cache first strategy in one of my apps, and had to force all my queries to { fetchPolicy: 'network-only' }. I am not using next.js but thought I would mention it

antondomratchev avatar Feb 25 '20 21:02 antondomratchev

I have the same problem. Query is:

const {
    data, error, loading,
  } = useQuery((store) =>
    store.queryHerkunft({
      where: { id: { _eq: id } },
    }),
  )

When id changes due to navigating to different dataset, the component re-renders but the query is not re-run. So stale data is shown.

barbalex avatar May 12 '20 12:05 barbalex

@barbalex have you tried with a different fetch policy? are you using data off data or out of the store?

chrisdrackett avatar May 12 '20 15:05 chrisdrackett

Fetch policy is unchanged so I guess that would be "cache-and-network".

I am using the data off data. Having started to move from apollo to mst-gql only two days ago I haven't even thought of doing it differently yet.

barbalex avatar May 12 '20 15:05 barbalex

As usual this dataset is accessible from a list that was loaded before. But for the list not all the fields are loaded. That is why I was using data from the query off data.

I have tried loading all fields for the list and then finding the dataset from that data to show it. While that does work (the find command runs when the component is re-rendered and returns the correct data), it seems like over-fetching is not a good general solution.

Also: because in my case references return undefined (https://github.com/mobxjs/mst-gql/issues/229), I can't do that when references are needed.

barbalex avatar May 12 '20 19:05 barbalex

have you tried with a different fetch policy?

Yes: network-only and cache-first. Did not make any difference.

barbalex avatar May 12 '20 19:05 barbalex

and all the things coming down have a typename and ID? sorry, trying to be helpful :)

chrisdrackett avatar May 13 '20 04:05 chrisdrackett

@chrisdrackett that is very helpful. You are right: The response comes without __typename. So that will be the reason.

I am querying using a graphql-tag based query because otherwise referenced tables will not arrive (https://github.com/mobxjs/mst-gql/issues/229).

Unfortunately when I add __typename to my fragments that provokes an error. Will have to solve that:

[mobx-state-tree] Error while converting `{"id":"3d0734a0-9448-11ea-ad59-b16356755fa5","art_id":null,"kultur_option":{"kultur_id":"3d0734a0-9448-11ea-ad59-b16356755fa5","ev_datum":true,"ev_geplant":true,"ev_person_id":true,"ev_teilkultur_id":true,"tk":false,"tk_bemerkungen":true,"tz_andere_menge":true,"tz_anzahl......:null}}` to `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))`: snapshot `{"id":"3d0734a0-9448-11ea-ad59-b16356755fa5","art_id":null,"kultur_option":{"kultur_id":"3d0734a0-9448-11ea-ad59-b16356755fa5","ev_datum":true,"ev_geplant":true,"ev_person_id":true,"ev_teilkultur_id":true,"tk":false,"tk_bemerkungen":true,"tz_andere_menge":true,"tz_anzahl_mutterpflanzen":true,"tz_auspflanzbereit_beschreibung":true,"tz_teilkultur_id":true,"tz_bemerkungen":true,"z_bemerkungen":true,"_rev":null,"_parent_rev":null,"_revisions":null,"_depth":1,"_conflicts":null}}` is not assignable to type: `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` (No type is applicable for the union), expected an instance of `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` or a snapshot like `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` instead. snapshot `{"id":"3d0734a0-9448-11ea-ad59-b16356755fa5","art_id":null,"kultur_option":{"kultur_id":"3d0734a0-9448-11ea-ad59-b16356755fa5","ev_datum":true,"ev_geplant":true,"ev_person_id":true,"ev_teilkultur_id":true,"tk":false,"tk_bemerkungen":true,"tz_andere_menge":true,"tz_anzahl_mutterpflanzen":true,"tz_auspflanzbereit_beschreibung":true,"tz_teilkultur_id":true,"tz_bemerkungen":true,"z_bemerkungen":true,"_rev":null,"_parent_rev":null,"_revisions":null,"_depth":1,"_conflicts":null}}` is not assignable to type: `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` (Value is not a undefined), expected an instance of `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` or a snapshot like `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` instead. snapshot `{"id":"3d0734a0-9448-11ea-ad59-b16356755fa5","art_id":null,"kultur_option":{"kultur_id":"3d0734a0-9448-11ea-ad59-b16356755fa5","ev_datum":true,"ev_geplant":true,"ev_person_id":true,"ev_teilkultur_id":true,"tk":false,"tk_bemerkungen":true,"tz_andere_menge":true,"tz_anzahl_mutterpflanzen":true,"tz_auspflanzbereit_beschreibung":true,"tz_teilkultur_id":true,"tz_bemerkungen":true,"z_bemerkungen":true,"_rev":null,"_parent_rev":null,"_revisions":null,"_depth":1,"_conflicts":null}}` is not assignable to type: `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` (Value is not a null), expected an instance of `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` or a snapshot like `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` instead. snapshot `{"id":"3d0734a0-9448-11ea-ad59-b16356755fa5","art_id":null,"kultur_option":{"kultur_id":"3d0734a0-9448-11ea-ad59-b16356755fa5","ev_datum":true,"ev_geplant":true,"ev_person_id":true,"ev_teilkultur_id":true,"tk":false,"tk_bemerkungen":true,"tz_andere_menge":true,"tz_anzahl_mutterpflanzen":true,"tz_auspflanzbereit_beschreibung":true,"tz_teilkultur_id":true,"tz_bemerkungen":true,"z_bemerkungen":true,"_rev":null,"_parent_rev":null,"_revisions":null,"_depth":1,"_conflicts":null}}` is not assignable to type: `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` (Value is not a valid identifier, which is a string or a number), expected an instance of `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` or a snapshot like `(undefined | null | reference(late(function () { return _kulturModel__WEBPACK_IMPORTED_MODULE_5__["kulturModel"]; })))` instead.

The query is (with __typename added):

const eventQuery = gql`
  query EventQueryForEvent(
    $id: uuid!
    $filter: event_bool_exp!
    $isFiltered: Boolean!
  ) {
    event(where: { id: { _eq: $id } }) {
      ...EventFields
      __typename
      kultur {
        id
        art_id
        kultur_option {
          ...KulturOptionFields
        }
      }
    }
    rowsUnfiltered: event @include(if: $isFiltered) {
      id
    }
    rowsFiltered: event(where: $filter) @include(if: $isFiltered) {
      id
    }
  }
  ${eventFragment}
  ${kulturOptionFragment}
`

And the model is:

export const eventModelBase = ModelBase
  .named('event')
  .props({
    __typename: types.optional(types.literal("event"), "event"),
    _conflicts: types.union(types.undefined, types.null, types.frozen()),
    _depth: types.union(types.undefined, types.null, types.integer),
    _parent_rev: types.union(types.undefined, types.null, types.string),
    _rev: types.union(types.undefined, types.null, types.string),
    _revisions: types.union(types.undefined, types.null, types.frozen()),
    beschreibung: types.union(types.undefined, types.null, types.string),
    changed: types.union(types.undefined, types.null, types.frozen()),
    changed_by: types.union(types.undefined, types.null, types.string),
    datum: types.union(types.undefined, types.null, types.frozen()),
    geplant: types.union(types.undefined, types.null, types.boolean),
    id: types.identifier,
    kultur: types.union(types.undefined, types.null, MSTGQLRef(types.late(() => kulturModel))),
    kultur_id: types.union(types.undefined, types.null, types.frozen()),
    person: types.union(types.undefined, types.null, MSTGQLRef(types.late(() => personModel))),
    person_id: types.union(types.undefined, types.null, types.frozen()),
    teilkultur: types.union(types.undefined, types.null, MSTGQLRef(types.late(() => teilkulturModel))),
    teilkultur_id: types.union(types.undefined, types.null, types.frozen()),
    tsv: types.union(types.undefined, types.null, types.frozen()),
  })
  .views(self => ({
    get store() {
      return self.__getStore()
    }
  }))

barbalex avatar May 14 '20 08:05 barbalex

O.k., solved above error (__typename was missing in a nested fragment).

But the original problem remains, even though now all data is returned with id and __typename:

{
  "data": {
    "event": [
      {
        "id": "ca7019e0-9445-11ea-b529-e7e8445751c9",
        "kultur_id": null,
        "teilkultur_id": null,
        "person_id": null,
        "beschreibung": null,
        "geplant": false,
        "datum": null,
        "changed": "2020-05-12",
        "changed_by": null,
        "_rev": "1-1441a7909c087dbbe7ce59881b9df8b9",
        "_parent_rev": null,
        "_revisions": ["1-1441a7909c087dbbe7ce59881b9df8b9"],
        "_depth": 1,
        "_conflicts": [],
        "__typename": "event",
        "kultur": null
      }
    ],
    "rowsUnfiltered": [
      { "id": "ca7019e0-9445-11ea-b529-e7e8445751c9", "__typename": "event" },
      { "id": "226ddce2-9444-11ea-b0ef-430f364f97aa", "__typename": "event" }
    ],
    "rowsFiltered": [
      { "id": "ca7019e0-9445-11ea-b529-e7e8445751c9", "__typename": "event" },
      { "id": "226ddce2-9444-11ea-b0ef-430f364f97aa", "__typename": "event" }
    ]
  }
}

barbalex avatar May 14 '20 09:05 barbalex

~~After diligently adding __typename to all queries and fragments it seems this was the solution.~~ ~~Thanks for your help @chrisdrackett~~

Nope. Problem remains. Meanwhile I am a bit confused, as may be visible from this back and forth...

barbalex avatar May 14 '20 11:05 barbalex

So to bring it to the point again:

This query:

const { data, error, loading } = useQuery((store) =>
  store.queryHerkunft({
    where: { id: { _eq: id } },
  }),
)

receives this answer:

{
  "data": {
    "herkunft": [
      {
        "__typename": "herkunft",
        "id": "05bb4fa0-93ca-11ea-ab80-97590c0e1653",
        "_conflicts": [],
        "_depth": 1,
        "_parent_rev": null,
        "_rev": "1-1441a7909c087dbbe7ce59881b9df8b9",
        "_revisions": ["1-1441a7909c087dbbe7ce59881b9df8b9"],
        "bemerkungen": null,
        "changed": "2020-05-11",
        "changed_by": null,
        "gemeinde": null,
        "geom_point": null,
        "kanton": null,
        "land": null,
        "lokalname": null,
        "lv95_x": null,
        "lv95_y": null,
        "nr": "3",
        "tsv": "'3':1A",
        "wgs84_lat": null,
        "wgs84_long": null
      }
    ]
  }
}

And when the component is re-rendered with a new id due to a change of dataset, the query is not re-queried.

Some more info:

The type is:

type herkunft {
  _conflicts: _text
  _depth: Int
  _parent_rev: String
  _rev: String
  _revisions: _text
  bemerkungen: String
  changed: date
  changed_by: String
  gemeinde: String
  geom_point: geometry

  # An array relationship
  herkunft_files(
    # distinct select on columns
    distinct_on: [herkunft_file_select_column!]

    # limit the number of rows returned
    limit: Int

    # skip the first n rows. Use only with order_by
    offset: Int

    # sort the rows by one or more columns
    order_by: [herkunft_file_order_by!]

    # filter the rows returned
    where: herkunft_file_bool_exp
  ): [herkunft_file!]!

  # An aggregated array relationship
  herkunft_files_aggregate(
    # distinct select on columns
    distinct_on: [herkunft_file_select_column!]

    # limit the number of rows returned
    limit: Int

    # skip the first n rows. Use only with order_by
    offset: Int

    # sort the rows by one or more columns
    order_by: [herkunft_file_order_by!]

    # filter the rows returned
    where: herkunft_file_bool_exp
  ): herkunft_file_aggregate!

  # An array relationship
  herkunft_sums(
    # distinct select on columns
    distinct_on: [herkunft_sums_select_column!]

    # limit the number of rows returned
    limit: Int

    # skip the first n rows. Use only with order_by
    offset: Int

    # sort the rows by one or more columns
    order_by: [herkunft_sums_order_by!]

    # filter the rows returned
    where: herkunft_sums_bool_exp
  ): [herkunft_sums!]!

  # An aggregated array relationship
  herkunft_sums_aggregate(
    # distinct select on columns
    distinct_on: [herkunft_sums_select_column!]

    # limit the number of rows returned
    limit: Int

    # skip the first n rows. Use only with order_by
    offset: Int

    # sort the rows by one or more columns
    order_by: [herkunft_sums_order_by!]

    # filter the rows returned
    where: herkunft_sums_bool_exp
  ): herkunft_sums_aggregate!
  id: ID!
  kanton: String

  # An array relationship
  kulturs(
    # distinct select on columns
    distinct_on: [kultur_select_column!]

    # limit the number of rows returned
    limit: Int

    # skip the first n rows. Use only with order_by
    offset: Int

    # sort the rows by one or more columns
    order_by: [kultur_order_by!]

    # filter the rows returned
    where: kultur_bool_exp
  ): [kultur!]!

  # An aggregated array relationship
  kulturs_aggregate(
    # distinct select on columns
    distinct_on: [kultur_select_column!]

    # limit the number of rows returned
    limit: Int

    # skip the first n rows. Use only with order_by
    offset: Int

    # sort the rows by one or more columns
    order_by: [kultur_order_by!]

    # filter the rows returned
    where: kultur_bool_exp
  ): kultur_aggregate!
  land: String
  lokalname: String
  lv95_x: numeric
  lv95_y: numeric
  nr: String

  # An array relationship
  sammlungs(
    # distinct select on columns
    distinct_on: [sammlung_select_column!]

    # limit the number of rows returned
    limit: Int

    # skip the first n rows. Use only with order_by
    offset: Int

    # sort the rows by one or more columns
    order_by: [sammlung_order_by!]

    # filter the rows returned
    where: sammlung_bool_exp
  ): [sammlung!]!

  # An aggregated array relationship
  sammlungs_aggregate(
    # distinct select on columns
    distinct_on: [sammlung_select_column!]

    # limit the number of rows returned
    limit: Int

    # skip the first n rows. Use only with order_by
    offset: Int

    # sort the rows by one or more columns
    order_by: [sammlung_order_by!]

    # filter the rows returned
    where: sammlung_bool_exp
  ): sammlung_aggregate!
  tsv: tsvector
  wgs84_lat: numeric
  wgs84_long: numeric
}

herkunftModel.base.js is:

export const herkunftModelBase = ModelBase
  .named('herkunft')
  .props({
    __typename: types.optional(types.literal("herkunft"), "herkunft"),
    _conflicts: types.union(types.undefined, types.null, types.frozen()),
    _depth: types.union(types.undefined, types.null, types.integer),
    _parent_rev: types.union(types.undefined, types.null, types.string),
    _rev: types.union(types.undefined, types.null, types.string),
    _revisions: types.union(types.undefined, types.null, types.frozen()),
    bemerkungen: types.union(types.undefined, types.null, types.string),
    changed: types.union(types.undefined, types.null, types.frozen()),
    changed_by: types.union(types.undefined, types.null, types.string),
    gemeinde: types.union(types.undefined, types.null, types.string),
    geom_point: types.union(types.undefined, types.null, types.frozen()),
    herkunft_files: types.union(types.undefined, types.array(MSTGQLRef(types.late(() => herkunft_fileModel)))),
    herkunft_files_aggregate: types.union(types.undefined, types.late(() => herkunft_file_aggregateModel)),
    herkunft_sums: types.union(types.undefined, types.array(types.late(() => herkunft_sumsModel))),
    herkunft_sums_aggregate: types.union(types.undefined, types.late(() => herkunft_sums_aggregateModel)),
    id: types.identifier,
    kanton: types.union(types.undefined, types.null, types.string),
    kulturs: types.union(types.undefined, types.array(MSTGQLRef(types.late(() => kulturModel)))),
    kulturs_aggregate: types.union(types.undefined, types.late(() => kultur_aggregateModel)),
    land: types.union(types.undefined, types.null, types.string),
    lokalname: types.union(types.undefined, types.null, types.string),
    lv95_x: types.union(types.undefined, types.null, types.frozen()),
    lv95_y: types.union(types.undefined, types.null, types.frozen()),
    nr: types.union(types.undefined, types.null, types.string),
    sammlungs: types.union(types.undefined, types.array(MSTGQLRef(types.late(() => sammlungModel)))),
    sammlungs_aggregate: types.union(types.undefined, types.late(() => sammlung_aggregateModel)),
    tsv: types.union(types.undefined, types.null, types.frozen()),
    wgs84_lat: types.union(types.undefined, types.null, types.frozen()),
    wgs84_long: types.union(types.undefined, types.null, types.frozen()),
  })

The query's model is:

queryHerkunft(variables, resultSelector = herkunftModelPrimitives.toString(), options = {}) {
  return self.query(`query herkunft($distinct_on: [herkunft_select_column!], $limit: Int, $offset: Int, $order_by: [herkunft_order_by!], $where: herkunft_bool_exp) { herkunft(distinct_on: $distinct_on, limit: $limit, offset: $offset, order_by: $order_by, where: $where) {
    ${typeof resultSelector === "function" ? resultSelector(new herkunftModelSelector()).toString() : resultSelector}
  } }`, variables, options)
}

barbalex avatar May 14 '20 12:05 barbalex

Meanwhile it is working for me. I am not sure but I think it is because now in the component I am not using the data returned by the query but rather directly grabbing the object from the store:

store.herkunfts.get(id)

Which gives this rather weird looking code:

const { error, loading } = useQuery((store) =>
  store.queryHerkunft({
    where: { id: { _eq: id } },
  }),
)

const row = store.herkunfts.get(id)

So the query is still needed to ensure the data is fetched from the server to the store. And it's loading and error methods are also used. But it's data is ignored. Instead the data is grabbed from the store.

This needs some getting used to, for me. And please tell me if I am getting something completely wrong. But so far this works.

barbalex avatar May 16 '20 10:05 barbalex

To come back to the original issue: Is it possible that while the data is re-fetched after variables change and the store is updated, the data key of the result is not?

barbalex avatar May 16 '20 10:05 barbalex

This would be relevant to me because I have other queries that I seem to have to use fragments in because they filter depending on related data. Which may not exist in the store yet. So I (think I) can't easily grab them directly from the store and instead rely on the data being updated after component re-renders.

But I could simply be a bit confused and miss something obvious.

barbalex avatar May 16 '20 10:05 barbalex

I found another case where this happens. This time it may happen because mst-gql does not allow combined primary keys/identifiers:

I am using a fragment to query:

const query = gql`
  query herkunftForConflictQuery($id: uuid!, $rev: String!) {
    herkunft_rev(where: { id: { _eq: $id }, _rev: { _eq: $rev } }) {
      _rev
      _deleted
      _depth
      _parent_rev
      _revisions
      bemerkungen
      changed
      changed_by
      gemeinde
      geom_point
      id
      kanton
      land
      lokalname
      nr
    }
  }
`

This is the query:

const { data, error, loading } = useQuery(query, {
  variables: { rev, id },
})

In this case herkunf_revModel.base.js contains:

export const herkunft_revModelBase = ModelBase
  .named('herkunft_rev')
  .props({
    __typename: types.optional(types.literal("herkunft_rev"), "herkunft_rev"),
    _deleted: types.union(types.undefined, types.null, types.boolean),
    _depth: types.union(types.undefined, types.null, types.integer),
    _parent_rev: types.union(types.undefined, types.null, types.string),
    _rev: types.union(types.undefined, types.string),
    _revisions: types.union(types.undefined, types.null, types.frozen()),
    bemerkungen: types.union(types.undefined, types.null, types.string),
    changed: types.union(types.undefined, types.null, types.frozen()),
    changed_by: types.union(types.undefined, types.null, types.string),
    gemeinde: types.union(types.undefined, types.null, types.string),
    geom_point: types.union(types.undefined, types.null, types.frozen()),
    id: types.identifier,
    kanton: types.union(types.undefined, types.null, types.string),
    kulturs: types.union(types.undefined, types.array(MSTGQLRef(types.late(() => kulturModel)))),
    kulturs_aggregate: types.union(types.undefined, types.late(() => kultur_aggregateModel)),
    land: types.union(types.undefined, types.null, types.string),
    lokalname: types.union(types.undefined, types.null, types.string),
    nr: types.union(types.undefined, types.null, types.string),
    sammlungs: types.union(types.undefined, types.array(MSTGQLRef(types.late(() => sammlungModel)))),
    sammlungs_aggregate: types.union(types.undefined, types.late(() => sammlung_aggregateModel)),
  })
  .views(self => ({
    get store() {
      return self.__getStore()
    }
  }))

herkunft_rev is defined in PostgreSQL as:

create table herkunft_rev (
  id uuid default uuid_generate_v1mc(),
  nr text default null,
  lokalname text default null,
  gemeinde text default null,
  kanton text default null,
  land text default null,
  geom_point geometry(Point, 4326) default null,
  bemerkungen text default null,
  changed timestamp default now(),
  changed_by text default null,
  _rev text default null,
  _parent_rev text default null,
  _revisions text[] default null,
  _depth integer default 1,
  _deleted boolean default false,
  primary key (id, _rev)
);

The graphql.schema looks like this (relationships removed):

type herkunft_rev {
  _deleted: Boolean
  _depth: Int
  _parent_rev: String
  _rev: String!
  _revisions: _text
  bemerkungen: String
  changed: date
  changed_by: String
  gemeinde: String
  geom_point: geometry
  id: ID!
  kanton: String
  land: String
  lokalname: String
  nr: String
}

id: ID! is set because I replaced hasura's uuid! with ID!

But here the problem is that the primary key is combined by id and _rev. That is because the app is offline capable and using the CouchDB method to track conflicts.

I have a feeling that this could lead to the unexpected behavior we are seeing: That the query is not re-queried. After all, the key mst-gql has declared identifier id has not changed.

barbalex avatar May 17 '20 15:05 barbalex

This problem goes back to mst itself: there can be only one identifier property: https://mobx-state-tree.js.org/concepts/references#identifiers

barbalex avatar May 17 '20 15:05 barbalex

I am also running into this issue with plain create-react-app. The component re-renders with updated props, but those props don't get expose to useQuery.

cmcaboy avatar May 31 '20 14:05 cmcaboy

I was able to get around it with useEffect and setQuery. It's kind of hacky, but it does work.

const { loading, data, error, store, setQuery } = useQuery((store) =>
    store.queryFund(
      { where: { id: fund_id } },
      (qb) => qb.capital_deployed.last_update.capital_deployed_change)
  );

  useEffect(() => {
    // prop fund_id changed
    const query = store.queryFund(
      { where: { id: fund_id } },
      (qb) => qb.capital_deployed.last_update.capital_deployed_change);
    setQuery(query);
}, [fund_id])
... render stuff

cmcaboy avatar May 31 '20 14:05 cmcaboy

@chrisdrackett any thoughts on this issue? I'm facing same set of problems. An app bootstrapped with CRA. The component re-renders with updated props. However, the query doesn't get re-triggered. No issue of multiple IDs. Tried 'network-only' policy too. Nothing. If I replace mst useQuery with sth built on vanilla fetch, things work as normal.

   export const BookDetailsRoute = observer((props: any) => {
        const id = props.match.params.id!;
        const { store, data } = useQuery(store =>
            store.queryBook_by_pk({ id }, BOOK_FRAGMENT)
        )
        // m = store.books.get(id);
        m = data?.book_by_pk;
       if (m) {
           return <BookDetails m={m} />;
       }
       return <EmptyItem />;
  }

baskin avatar Jun 06 '20 21:06 baskin

Does this line mean that in my case above, where I'm passing the query as a function (store => store.queryBook_by_pk({ id }, BOOK_FRAGMENT), the effect will be skipped?. Pardon my ignorance, I'm relatively new to react. I was going through this code trying to reason how setQuery would be called in case my id above changes.

baskin avatar Jun 06 '20 21:06 baskin

@baskin I had the same problem and the line you linked is responsible for only fetching it once.

My solution to this problem is this:

const { data, loading, setQuery } = useQuery();

React.useEffect(() => {
  setQuery((store) => store.queryBook_by_pk({ id }, BOOK_FRAGMENT));
}, [id]);

danielbischoff avatar Oct 03 '20 19:10 danielbischoff

I ending up using React.useEffect too. In my case it was an array so I did something like that:

const query = (store: RootStoreType) =>
    store.queryParticipants(
        {
            filter: {
                id_in: ui.favorites,
            },
        },
        (participant) =>
            participant.firstname.lastname.dob.country(
                (country) => country.emoji
            )
    );

const { loading, data, setQuery } = useQuery(query);

React.useEffect(() => {
    setQuery(query);
}, [ui.favorites.length]);

Almaju avatar Aug 10 '21 17:08 Almaju

What the heck!? How is this not easily answered? It seems like we are all trying to do something the wrong way?

alisman avatar Aug 15 '22 21:08 alisman

any updates? :)

ShawkiS avatar Sep 24 '22 21:09 ShawkiS