Closed frederikhors closed 7 months ago
Summary
Upgrading from
@urql/svelte
1 to 2 I missedreexecute()
which is very useful sometimes when not using the reactive mode ($:
) that Svelte offers.Proposed Solution
Can we re-add it, @jonathanstanley?
Notes
It is been asked from other people too:
@francois-blanchard: https://github.com/urql-graphql/urql/pull/2370#issuecomment-1153191285
@rouzwelt: https://github.com/urql-graphql/urql/pull/2370#issuecomment-1172977813
(BTW: did you find an alternative way?)
I figured out a workaround using svelte reactive block
I figured out a workaround using svelte reactive block
Thanks, can you show us?
I figured out a workaround using svelte reactive block
Thanks, can you show us?
sure, take a look here: https://github.com/rainprotocol/rain-toolkit-gui/blob/304e6b49d4d365f0a358f9bad6c46a485d927213/src/routes/sale/SaleChart.svelte#L65
the refresh()
method is responsible for performing a similar thing to reexecute()
, which is bound to a spinning arrow button on html.
a few lines higher you can see the query is also bound to a svelte reactive variable. Hope it helps, let me know if you have any questions
The docs state another method: https://formidable.com/open-source/urql/docs/basics/svelte/#reexecuting-queries
And there's also options to reassign the original store, so I'm not sure there's anything here that warrants implementing unless:
Thanks for the answer, @kitten.
In Svelte is very frequent to have code like:
<script lang="ts">
import { queryStore, gql, getContextClient } from '@urql/svelte';
export let condition;
export let pagination;
export let orderBy;
export let canBeVisible;
const client = getContextClient();
const query = gql`
query {
todos {
id
title
}
}
`
$: todos = queryStore({
client,
query,
variables: {
input: {
pagination,
condition: {
...condition,
player: { name: true },
show_team: { name: true },
},
orderBy,
}
},
pause: !canBeVisible,
});
</script>
The code you propose in docs:
function refresh() {
queryStore({
client,
query,
requestPolicy: 'network-only'
});
}
forces us to repeat many of the instructions already contained in $: todos...
(e.g.: pause
, variables
and we should make them $: reactive too).
Sometimes we need to be really fast in coding and we would like to avoid writing a custom refresh()
function if we can (even in templates) call directly:
<button on:click={() => todos.reexecute()}>Refresh results</button>
It would be amazing to have a reexecute()
method to use, such as:
$: todos = queryStore({
client,
query,
//...
});
// So I can use anywhere:
todos.reexecute()
ran into the mimssing reexecute()
tonight where i wanted to poll on an interval, here is a relatively svelte-y reactive workaround. hope this is helpful for others.
// $lib/queries.ts
import {
type AnyVariables,
getContextClient,
gql,
type QueryArgs,
queryStore,
type OperationResultState,
} from '@urql/svelte'
import { derived, readable, writable } from 'svelte/store'
function withPolling<Data = unknown, Variables extends AnyVariables = AnyVariables>(
queryArgs: QueryArgs<Data, Variables>,
) {
const initial = queryStore(queryArgs)
const result = writable<OperationResultState<Data, Variables>>()
const query = derived([initial, result], ([initial, next]) => {
return next || initial
})
return {
...query,
refresh,
poll,
}
function refresh() {
return new Promise<Data>((resolve, reject) => {
queryStore<Data, Variables>({ ...queryArgs, requestPolicy: 'network-only' }).subscribe(
($data) => {
result.set($data)
if ($data.error) {
reject($data.error)
} else if ($data.data) {
resolve($data.data)
}
},
)
})
}
function poll(intervalMs = 5_000) {
const lastUpdated = readable(new Date(), (set) => {
const timeout = setInterval(interval, intervalMs)
return () => {
clearInterval(timeout)
}
function interval() {
refresh().catch(console.error)
set(new Date())
}
})
const polling = derived([query, lastUpdated], ([query, lastUpdated]) => ({
...query,
lastUpdated,
}))
return {
...polling,
refresh,
}
}
}
export function queryTodos() {
return withPolling({
client: getContextClient(),
query: gql`
query {
todos {
id
title
}
}
`,
})
}
<script lang="ts">
import { queryTodos } from '$lib/queries'
const query = queryTodos().poll()
$: todos = $query.data?.todos
function refresh() {
// this will also update todos above
query.refresh().then(console.log).catch(console.error)
}
</script>
<button on:click={refresh}>Refresh</button>
<pre>{JSON.stringify(todos)}</pre>
Summary
Upgrading from
@urql/svelte
1 to 2 I missedreexecute()
which is very useful sometimes when not using the reactive mode ($:
) that Svelte offers.Proposed Solution
Can we re-add it, @jonathanstanley?
Notes
It is been asked from other people too:
@francois-blanchard: https://github.com/urql-graphql/urql/pull/2370#issuecomment-1153191285
@rouzwelt: https://github.com/urql-graphql/urql/pull/2370#issuecomment-1172977813
(BTW: did you find an alternative way?)