AbortController not working in Firefox/sveltekit - sveltekit

Window.fetch: 'signal' member of RequestInit does not implement interface AbortSignal.
I think its with SSR, but not sure.

Related

What's the type of React Query's Error and how to handle different cases?

I'm using React Query with typescript to fetch data in my project and I'm trying to use the error the useQuery hook returns to display a message describing the error if it exists like this :
{isError && (error)? <p className=" text-[#ff0000] text-center font-semibold">{error?.response.data.message}</p> : null}
I'm having a problem with the error type :
How can I fix it, I couldn't find anything on the internet and if possible can anyone explain how to handle different thrown error with react query since you can throw anything in JS/TS
error defaults to type unknown because your queryFn can throw anything, that's a javascript behaviour. throw 5 will give you number as your error type. There is no good way to assert that, so unknown is the best possible type. It's also what TypeScript does now per default since v4.4 (useUnknownInCatchVariables)
The best way to make sure that your app runs as you want is to narrow the type at runtime. if (error instanceof Error) does the trick, and the you can safely access error.message.
If you are using axios, the type is actually an AxiosError, and axios has an axios.isAxiosError(error) helper that checks for that and also narrows the type correctly.
The alternative is to provide generics to useQuery:
useQuery<Todo[], AxiosError>(['todos'], fetchTodos)
but this is bad for a couple of reasons:
there are actually four generics, and you remove a bunch of features by only providing two of them
There is no guarantee that your error will really be an axios error. For example, if you use select, and a runtime error happens in there (because of some faulty logic), your error will be a "normal" Error, but not an axios Error.
Alas, as you can throw anything in JS, unknown is the most correct type.
I'm also going into more details in my blog:
https://tkdodo.eu/blog/react-query-and-type-script
As #TkDodo has pointed out, you could provide generics to useQuery but it's not worth it, since you will lose the Type inference too.
However, as a workaround, I add the onError callback and type its error arg instead. TypeScript will infer the type of that error to the type I am expecting from useQuery.
Note that I am using Axios request & response interceptors for all requests that I use to format and throw my custom errors.
Example...
interface IPayload {
someKey: string; // ETC
}
// The type of error expected from the response (also formatted by interceptor).
interface IApiError {
message: string;
description: string;
statusCode: string | number;
}
export const useMyQuery = (payload: IPayload) => {
const { data, isLoading, isError, error, refetch } = useQuery({
queryKey: ['some', 'query-keys'],
queryFn: () => API.fetchMyData(payload),
// This does the trick
onError: (err: IApiError) => err,
});
};
I had same issue with Typescript and react-query, same error Object is of type 'unknown'.
Installing this devDependency "#types/react-query" helped me somehow. I am using VS Code editor and I think that helped with type suggestions. This might help.
npm i --save-dev #types/react-query
For Mutation only:
If you are using Axios for Api calls, use the following to get Axios type errors:
const error = mutation.error as AxiosError;
Now, the error object will not throw any object not found warning.

How to use service-worker background sync with typescript

I created a react project with TS (npx create-react-app my-app --template cra-template-pwa-typescript).
I followed the documentation : https://developers.google.com/web/updates/2015/12/background-sync). The following code is producing TS errors (even if it works):
// Register your service worker:
navigator.serviceWorker.register('/sw.js');
// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
return swRegistration.sync.register('myFirstSync'); // error
});
self.addEventListener('sync', function(event) {
if (event.tag == 'syncSavedProjects') { // error
event.waitUntil(doSomeStuff()); // error
}
});
Property 'sync' does not exist on type 'ServiceWorkerRegistration'
Property 'tag' does not exist on type 'Event'
Property 'waitUntil' does not exist on type 'Event'
Looks like definitions are missing (lib.dom.d.ts)
There are a number of types that were removed from the standard type libraries in TypeScript v4.4.0, as described in this issue. Primarily, these are types related to web platform features that are not widely implemented (e.g. features that are Chrome-only at the moment). Background sync falls into that category.
The long-term plan is apparently, starting with TypeScript v4.5.0, to use standalone libraries like #types/web and #types/serviceworker, instead of the standard libraries that are updated with each TypeScript release. This means that in the future, upgrading your TypeScript dependency can be done independently from your type definition dependencies.
However, those libraries also have a policy of not including interfaces that are only available in a single browser. So I don't think that background sync is exposed in them either. There might be another #types/... library that does have them, but I have no been able to find them yet.
So, in terms of an actual solution today, the best approach I've found is to add a local copy of the old definitions to your TypeScript project. Here's a snippet of how we did this in the Workbox project for the background sync defintions:
interface SyncManager {
getTags(): Promise<string[]>;
register(tag: string): Promise<void>;
}
declare global {
interface ServiceWorkerRegistration {
readonly sync: SyncManager;
}
interface SyncEvent extends ExtendableEvent {
readonly lastChance: boolean;
readonly tag: string;
}
interface ServiceWorkerGlobalScopeEventMap {
sync: SyncEvent;
}
}

How to validate async api response with Typescript

How do I validate my API response when storing it as an object. For example:
const { data } = await axios.get("/form");
How do I make sure this data conforms to:
interface Form {
title: string;
questions: Question[]
}
Typescript does not perform any type of validations out of the box like java or other strong typed languages.
Things like
const { data } = await axios.get<Form>("/form");
does not guarantee that the response data is of Form type. It is just used for static typing checks (no errors/validation in runtime). For having a guarantee I would recommend the implementation of a guard function (https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards) with some JSON schema validation. For example, you can use
https://www.npmjs.com/package/ajv or https://www.npmjs.com/package/joi package to do that.
Use:
const { data } = await axios.get<Form>("/form");
If you want to make sure that the incoming data is indeed compatible with Form interface, you have to do it in runtime (thus can't be done with TS). Checking runtime data is compatible with a type isn't always straightforward or easy (especially with nested data). io-ts is one of the libraries that does it.

Typescript type declarations for Promise that returns a React Component

I have the following function:
const withCacheRefresh = (lazyLoadComponent: any) => {
return new Promise<React.ComponentType<any>>((resolve) => {
lazyLoadComponent()
.then(resolve)
.catch(() => {
window.location.reload(true);
});
});
}
It takes in a promise as an argument, specifically lazy. I proceed to call the promise, either resolving the promise by returning the result of lazy, or in my catch, refresh the page. I'm running into issues with the following Typescript compilation error:
Type 'Promise<ComponentType<any>>' is not assignable to type 'Promise<{ default: ComponentType<any>; }>'.
Type 'ComponentType<any>' is not assignable to type '{ default: ComponentType<any>; }'.
Property 'default' is missing in type 'ComponentClass<any, any>' but required in type '{ default: ComponentType<any>; }'. TS2322
I have two questions:
How can I specify my first argument lazyLoadComponent to be of the type for a function that returns a component of React.Component<any> type instead of just any?
How can I fix my Promise<React.ComponentType<any>> definition such that it conforms to the required type of Promise<{ default: ComponentType<any>; }> ?
Update
I've received answers telling me that my solution is incorrect for my stated problem, but I purposely chose to omit details about the nuances of my larger problem space.
Since it was asked, I feel like there's no pain clarifying: when new deployments get released for my application, new chunks get created, and the old ones purged from the production workspace. Consequently, clients that still remain in the previous release (since the app hasn't been refreshed to the latest version) are still using old chunks. HMR would not work since this is a production environment. An explicit refresh would cause the service workers to retrieve the latest chunks.
A similar circumstance is described in this Github Issue.
This is a convoluted (and slightly incorrect) way of doing things.
I'm going to assume you have a reason for reloading the page on an error other than "I hope it fixes the error" (if that's the reason or if it's for cache-busting purposes, you should definitely try HMR).
EDIT Since OP has clarified what he meant, I'd suggest, instead of hoping the browser doesn't cache the lazy-loaded component and thereby errors when a new version is rolled out, to use a precache manifest in the Service Worker itself, which would allow the SW to load the manifest whenever a new one is regestired. See this question for more info. You can integrate it into the bundler itself with the Workbox plugin, even if you don't use Workbox.
I'm also going to assume you want to use this with lazy, not call it on lazy, because otherwise it's not exactly possible to catch any errors.
import React from 'react';
type LazyFactory = Parameters<typeof React.lazy>[0];
const withCacheRefresh = (
importResult: LazyFactory
): LazyFactory => () =>
importResult().catch(() => {
window.location.reload(true);
// Following makes return type `never`, which satisfies TypeScript
throw new Error('component load failed');
});
There's no need to wrap it in a promise because it already is one. You can just .catch on it directly.
Usage:
const MyLazyComponent = React.lazy(withCacheRefresh(() => import('./Component')));

What is "buildQuery" parameter in "aor-graphql-client"

I am trying to work with "aor-graphql-client". When I try to create REST-client like in documentation, I get the error that "buildQueryFactory" is not a function.
As I see, this function is using in here.
From this object wee see that param "buildFactory" must be defined in options or in defaultOptions.
{
client: clientOptions,
introspection,
resolveIntrospection,
buildQuery: buildQueryFactory,
override = {},
...otherOptions
} = merge({}, defaultOptions, options);
In defaultOptions this parameter isn't defined. In my options I now define only {client: {uri: ...}}, and I don't know what buildQuery means.
The documentation you are referring to is from a deprecated package not related to aor-graphql-client (it was in fact our first try at GraphQL with Admin-on-rest).
The aor-graphql-client package only provides the basic "glue" to use GraphQL with Admin-on-rest.
The buildQuery option is explained here. In a nutshell, it is responsible for translating your GraphQL implementation to admin-on-rest.
We provided a sample implementation targeting the Graphcool backend: aor-graphql-client-graphcool. Use it as a starting point for implementing your own until we find some time to make the aor-graphql-client-simple (which will be a rewrite of the aor-simple-graphql-client you are referring to).
Have fun!
what is the buildfieldlist imported in builduery?

Resources