Giter Club home page Giter Club logo

Comments (7)

AlexanderArvidsson avatar AlexanderArvidsson commented on May 23, 2024 1

@jerelmiller I absolutely agree! I definitely think the right path is the full options object, for type safety and consistency reasons.

My approach I added at the end was as a workaround that works today but shouldn't work in the future, and people could define that themselves in their code until we have proper skipToken support. Then, it would simply be switching the import to the proper skipToken.

from apollo-client.

alessbell avatar alessbell commented on May 23, 2024

Hi @vezaynk 👋

Can it be expanded to cover all query types?

We agree skipToken is a powerful API and have considered adding support for it in useQuery, but we don't have any official plans there yet. I'm not sure if you had something else/in addition in mind? Thanks for the feedback here.

from apollo-client.

vezaynk avatar vezaynk commented on May 23, 2024

@alessbell Is there a reason against it? Currently I'm writing a lot of code that looks like this:

const maybeVar: string | null;

useQuery({
  variables: {
     myVar: maybeVar as string // this cast shouldn't be necessary
  },
  skip: !maybeVar
})

code like this is better:

const maybeVar: string | null;

useQuery({
  variables: maybeVar ? {
     myVar: maybeVar
  } : skipToken,
})

from apollo-client.

alessbell avatar alessbell commented on May 23, 2024

We're big fans of skipToken too and wholeheartedly agree this pattern has significant DX benefits :)

We first introduced skipToken in the Suspense-enabled data fetching hooks in 3.8 as you noted, and we're about to ship 3.9 but this is useful signal as we plan 3.10 and beyond.

from apollo-client.

AlexanderArvidsson avatar AlexanderArvidsson commented on May 23, 2024

@alessbell Is there a reason against it? Currently I'm writing a lot of code that looks like this:

const maybeVar: string | null;

useQuery({
  variables: {
     myVar: maybeVar as string // this cast shouldn't be necessary
  },
  skip: !maybeVar
})

code like this is better:

const maybeVar: string | null;

useQuery({
  variables: maybeVar ? {
     myVar: maybeVar
  } : skipToken,
})

What you could do to avoid the nasty cast, is conditionally change the variables object:

const maybeVar: string | null;

useQuery(QUERY, {
  variables: maybeVar ? {
     myVar: maybeVar
  } : undefined,
  skip: !maybeVar
})

// Or:
useQuery(QUERY, maybeVar ? {
  variables: {
     myVar: maybeVar
  },
} : { skip: true })

It's definitely better if you have multiple variables, but I think the skipToken is a much better approach.

EDIT: See my next comment for a better workaround


I think a good discussion would be where skipToken is accepted? Consider the following:

useQuery(QUERY, {
  variables: maybeVar ? {
     myVar: maybeVar
  } : skipToken,
})

useQuery(QUERY, maybeVar ? {
  variables: {
     myVar: maybeVar
  },
}, skipToken)

The reason the latter approach is better is because it would make non-variable queries skippable with skipToken:

useQuery(QUERY, !maybeVar ? skipToken : undefined)
// Otherwise you end up with this nasty syntax for non-variable queries:
useQuery(QUERY, { variables: !maybeVar ? skipToken : {} }) // Doesn't make much sense

But that opens the question for the following pattern:

// Somewhat identical to RTK-Query.
useQuery(maybeVar ? QUERY : skipToken)

But then again, that's why we have the skip option:

useQuery(QUERY, { skip: !maybeVar })

It's not realistic to add all the above accepts for skipToken, so my proposal would be either only as the whole options object (worse DX for non-variable queries), or both the options object and query object (good DX for both cases).
For type-safety, having the options object accept skipToken is the only valid syntax, the query skipToken is just syntactic sugar.

If we support both, it should skip if at least any of the arguments have skipToken:

useQuery(skipToken, { variables: { ... } }) // Skip
useQuery(QUERY, skipToken) // Skip
useQuery(skipToken, skipToken) // Skip
useQuery(QUERY, { variables: { ... } })) // Don't skip

Perhaps unnecessary complexity, so for non-variable queries, stick with { skip: true }.

from apollo-client.

AlexanderArvidsson avatar AlexanderArvidsson commented on May 23, 2024

This form opens up a good point:

useQuery(QUERY, maybeVar ? {
  variables: {
     myVar: maybeVar
  },
} : { skip: true })

Because you can simply define skipToken yourself and be on your way:

export const skipToken = { skip: true }

useQuery(QUERY, maybeVar ? {
  variables: {
     myVar: maybeVar
  },
} : skipToken)

That said, skipToken should be a symbol, implemented by Apollo.

from apollo-client.

jerelmiller avatar jerelmiller commented on May 23, 2024

@AlexanderArvidsson for consistency reasons, we'll make skipToken a valid value for the entire options object. That way it will mimic the API on the suspense hooks.

useQuery(QUERY, skipToken) // valid
useQuery(QUERY, id ? { variables: { id } } : skipToken) // valid

useQuery(skipToken) // invalid
useQuery(QUERY, { variables: skipToken }) // invalid

The reason we went with this approach is to provide better TypeScript errors when your query has required variables and you haven't provided them. We should require you to define variables in options, otherwise your query is invalid. This is something the suspense hooks do, but unfortunately useQuery just doesn't support super well today. We want to do this work before we add support for skipToken to provide the best experience.

For that reason, we don't suggest this approach:

useQuery(QUERY, maybeVar ? {
  variables: {
     myVar: maybeVar
  },
} : { skip: true })

Once we get this work done, the above would be invalid (assuming myVar is required) since you aren't providing a variables option in your "else" case.

We have already started this work in #11241, but need some time to come back to it (6 million priorities don't help 😆). As @alessbell said, we're big fans of this pattern and its more of "when" not an "if" at this point.

from apollo-client.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.