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

readQuery without variables #1546

Closed
chrissm79 opened this issue Apr 4, 2017 · 13 comments
Closed

readQuery without variables #1546

chrissm79 opened this issue Apr 4, 2017 · 13 comments

Comments

@chrissm79
Copy link

Intended outcome:
I would like to be able to query the store without having to use the same variables in previous queries. For example, on a list page I have a query that looks like this:

query Company($cursor: String) {
    company {
      id
      locations(first: 10, after: $cursor) {
        pageInfo {
          # ...
        }
        edges {
          node {
            id
            # ...
          }
        }
      }
    }
}

I have a mutation to add a location and I'm attempting to load all locations associated with the company but it's forcing me to add the first and after field arguments. I would like to grab all locations by using the following query:

const data = this.props.client.readQuery({
  query: gql` {
    company {
      healthySpots {
        edges {
          node {
            id
            # ...
          }
        }
      }
    }
  }`,
});

Actual outcome:
The following error is being thrown:

Can't find field locations on object ($ROOT_QUERY.company) {
  "name": "App",
  "locations({\"first\":10,\"after\":null})": {
    "type": "id",
    "id": "$ROOT_QUERY.company.locations({\"first\":10,\"after\":null})",
    "generated": true
  },
  "__typename": "Company"
}.

If I include the first and after arguments with the same variables used on my list page then it works but this requires me to keep track of those variables from a different location in my app. It would be nice to just be able to skip variables if I preferred to not filter any fields.

How to reproduce the issue:
If you are attempting to read a query from the store that was fulfilled with the use of variables then an error will be thrown.

Also, I have to applaud your efforts that have allowed me to be so much more productive than I was before Apollo was open sourced! Thank you for what you're doing for the community!!

@helfer
Copy link
Contributor

helfer commented Apr 20, 2017

Hey @chrissm79. I think the right solution for your use case is a custom resolver, but you'll still have to keep track of the variables manually in order to know which queries to run against the store. We're going to make this a lot easier in the new API though.

@helfer helfer closed this as completed Apr 20, 2017
@spoeck
Copy link

spoeck commented Oct 4, 2017

@helfer Hi, I've the same issue. Are there any updates for the new API?

@devmetal
Copy link

Its still not easy, i have to track every single variables. The documentation holds just the easy use cases, but i have pagination, filtering and ordering, and the actions i have, modify records individually. The update mechanism is still hard and complicated

@minardimedia
Copy link

I also stuck with these problem, many solutions can be implemented like giving more flexibility to to readQuery( query: "queryName" ) returning the store with an array of all the stored variables

varialbe: "chri"
-Data 1
-Data 2
-Data 3
-Data 4
variable: "chris"
-Data 1
-Data2
etc

or have a more flexible refetchQuery('variableName') fire an update in ALL variables not just the last one set

The problem is readQuery and fetchQuery are very tight to pass ALWAYS variables, but they are many cases like a search, dynamic filters etc, where you don't have a trace off all the possible variables, the issue is when you try to add or remove elements

@nickluger
Copy link

This might be a big blocker for a lot of people, as the following seems a very common use case:

  1. Search, filter or paginate a list of things.
  2. Update, delete or add one of these things.
  3. Keep the search, filter, paginated view intact.

We're going to make this a lot easier in the new API though.

@helfer , i'm not sure how this becam easier in the new API? In case i'm missing something please post a link 😀.

Otherwise i would suggest re-opening this issue. This still seems especially cumbersome if you use

  • pagination (fetchMore) (Queries are merged -> which to use for update?)
  • or as stated above, any kind of filtering, search etc.

@chrissm79
Copy link
Author

Would love to see something like this built into apollo client, it's been a HUGE help. It wasn't originally published to NPM but it looks like they've done so recently.

Here a video w/ the creator: https://www.youtube.com/watch?v=8ZKpIB1pDw8&t=482s

@mrdulin
Copy link

mrdulin commented Jul 12, 2018

same issue.

Here is my angular + apollo code:

@Injectable()
export class RepoService {
  constructor(private apollo: Apollo) {}

  public getRepoByNameAndOwner(owner: string, name: string, first?: number): Observable<any> {
    return this.apollo
      .watchQuery<any>({
        query: RepoQuery,
        variables: {
          owner,
          name,
          first
        }
      })
      .valueChanges.map((res: any) => {
        const { data, ...rest } = res;
        return { repository: data.repository, ...rest };
      });
  }

  public updateTopics(updateTopicsInput: IUpdateTopicsInput): Observable<any> {
    return this.apollo.mutate<any>({
      mutation: M.updateTopics,
      variables: {
        input: updateTopicsInput
      },
      update: (proxy: DataProxy, mutationResult: FetchResult<any>) => {
        const data = proxy.readQuery({ query: RepoQuery, variables: { owner: '', name: '', first: '' } });
        debugger;
      }
    });
  }
}

It will throw an error like below:

Error: Can't find field repository({"name":"","owner":""}) on object (ROOT_QUERY) {
  "user({\"login\":\"mrdulin\"})": {
    "type": "id",
    "generated": true,
    "id": "$ROOT_QUERY.user({\"login\":\"mrdulin\"})",
    "typename": "User"
  },
  "repository({\"name\":\"react-tap-event-plugin-issues\",\"owner\":\"mrdulin\"})": {
    "type": "id",
    "generated": false,
    "id": "Repository:MDEwOlJlcG9zaXRvcnkxMTg4ODEyMjU=",
    "typename": "Repository"
  }
}.

Here is my solution, but I think this solution sucks. Like @chrissm79 said, I saved variables in my service for later using in proxy.readQuery() method.

I saved RepoQuery variables in "parent scope" - the repoQueryVariables, so it can be used in updateTopics function scope. That makes updateTopics method impure.

It's a serious issue.

@Injectable()
export class RepoService {
  constructor(private apollo: Apollo) {}
 
  // for saving "RepoQuery" variables
  private repoQueryVariables: any;

  public getRepoByNameAndOwner(owner: string, name: string, first?: number): Observable<any> {
    // save "RepoQuery" variables
    this.repoQueryVariables = {
      owner,
      name,
      first
    };
    return this.apollo
      .watchQuery<any>({
        query: RepoQuery,
        variables: this.repoQueryVariables
      })
      .valueChanges.map((res: any) => {
        const { data, ...rest } = res;
        return { repository: data.repository, ...rest };
      });
  }

  public updateTopics(updateTopicsInput: IUpdateTopicsInput): Observable<any> {
    return this.apollo.mutate<any>({
      mutation: M.updateTopics,
      variables: {
        input: updateTopicsInput
      },
      update: (proxy: DataProxy, mutationResult: FetchResult<any>) => {
        // use "this.repoQueryVariables"
        const data = proxy.readQuery({ query: RepoQuery, variables: this.repoQueryVariables });
        debugger;
      }
    });
  }
}

note: above code is a demo! Do not use it in any production environment!!

@gnuletik
Copy link

Still no clean solution ?

@kyosifov
Copy link

kyosifov commented May 9, 2020

This is really embarrassing, how we cannot access a query without variables. I don't think it will be much of a problem if we get queries with the same name. And we also can come up with different query names in GraphQL and get directly that query by the custom name, no by the whole GraphQL query with its variables.

It seems very frustrating to store queries with all their variables, just so we can update them later in some of the code. We need to create additional code even though apollo can crate an API that can be easily handled with custom name queries. With the custom names, we will not need to manage additional code for mutating queries.

Currently, in my real project, I have an add todo modal and want to modify the list that shows on the dashboard, to add the todo on top of the list, but I cannot access the query with readQuery, because it also requires the variables that are passed to the query. Well, this is a bummer because the components are not related.

I've been searching for any non-hacking ways, but it seems a bad API implementation to me.

Correct me if I am wrong.

@willwill96
Copy link

I would like to see this functionality as well, since our application has filtering, paging and sorting and we don't want to keep track of those variables throughout the entire application. I tried using the keyArgs option when initializing the InMemoryCache, excluding the filtering/sorting/paging variables from that list. The problem then, was that since keyArgs did not include those filtering/paging/sorting variables, the query was not re-running when the variables were updated. Would it be worth re-creating this ticket in @apollo/client? I'm not sure if this repo is actively monitored anymore

@mindnektar
Copy link

I've created a package in an attempt to solve these issues and make complex cache updates as painless as possible. https://www.npmjs.com/package/apollo-augmented-hooks

See https://github.com/appmotion/apollo-augmented-hooks/#--modifiers and the linked caching guide in particular.

I've been using this in production for a while now and just made it open source so other people can benefit from it as well.

@mikejackowski
Copy link

Any update on this?

@anthonyrende
Copy link

:(

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests