
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
use-query-rd
Advanced tools
A drop in replacement for apollo client's `useQuery` hook with a return type that mimics Elm's RemoteData ADT
use-query-rd A drop in replacement for apollo client's
useQueryhook with a return type that mimics Elm's RemoteData ADT
Tagging network bound data with the state of the request makes impossible states impossible. This is highly desirable as data requests and the subsequent handling of fetched data is a common cause of logic and runtime errors in apps.
This is a @apollo/client specific implementation of RemoteData. useQueryRd is a wrapper around useQuery that returns one additional property, _rd. _rd is a RemoteData that is generic across Success. Failure is not generic as it will always be ApolloError.
useQuery
function useQuery<TData = any, TVariables = OperationVariables>(
query: DocumentNode | TypedDocumentNode<TData, TVariables>,
options?: QueryHookOptions<TData, TVariables>
): QueryResult<TData, TVariables>;
useQueryRd
const useQueryRd: <TData, TVariables = OperationVariables>(
query: DocumentNode | TypedDocumentNode<TData, TVariables>,
options?: QueryHookOptions<TData, TVariables> | undefined
) => QueryResult<TData, TVariables> & {
_rd: RemoteData<TData>;
};
Takes a matcher and a RemoteData value. The matcher attributes the RemoteData value to a case and applies the matched function. match support partial matching by supplying a default tag of _. Any RemoteData states no supplied subsequent to the _ will fallback to the function supplied at _. A common use case for this is combining the functions for Initialized and Pending into one "loading" case.
const match: <T, D>(rd: RemoteData<D>, matcher: Matcher<T, D>) => T;
import React from "react";
import { useQueryRd, match } from "use-query-rd";
const ContainerComponent = (): JSX.Element =>
match(useQueryRd<{ data: MyDataType[] }>(GET_DATA_QUERY)._rd, {
_: <Skeleton />,
Failure: (error) => <MyErrorScreen error={err.error} />,
Success: (data: MyDataType) => <MySuccessScreen data={data.data.myData} />,
});
export default ContainerComponent;
Takes four functions corresponding to the four tags and a RemoteData value. The function corresponding to the tag of the value is applied.
const fold: <T, D>(
initialized: () => T,
pending: () => T,
failure: (error: ApolloError) => T,
success: (data: D) => T
) => (_: RemoteData<D>) => T;
import React from "react";
import { useQueryRd, fold } from "use-query-rd";
const ContainerComponent = (): JSX.Element =>
fold(
() => <Skeleton />,
() => <Skeleton />,
(error) => <MyErrorScreen error={err.error} />,
(data: MyDataType) => <MySuccessScreen data={data.data.myData} />
)(useQueryRd<{ data: MyDataType[] }>(GET_DATA_QUERY)._rd);
export default ContainerComponent;
Apply the supplied function to the RemoteData if tag is Success, otherwise return original RemoteData
const map: <T, D>(f: (a: T) => D, fa: RemoteData<T>) => RemoteData<D>;
const myInitialData = useSomeData()._rd;
const formattedData = map((res: MyResultType) => {
const manipulatedData = doSomething(res);
return {
myManipulatedData: manipulatedData,
};
}, myInitialData);
Put the results of two RemoteData calls together. Used to make mapX.
const andMap: <RD1, RD2>(
rd1: RemoteData<RD1>,
rd2: RemoteData<(d: RD1) => RD2>
) => RemoteData<RD2>;
Combine two remote data sources with the given function. The result will succeed when (and if) both sources succeed.
const map2: <D, D2, D3>(
f: (d: D) => (d2: D2) => D3,
rd1: RemoteData<D>,
rd2: RemoteData<D2>
) => RemoteData<D3>;
export const Map2Example = () => {
const RD1 = useQueryRd<{ launchesPast: Launch[] }>(ROCKETS_QUERY, {
variables: { limit: 100 },
})._rd;
const RD2 = useQueryRd<{ launchpads: Launchpad[] }>(LAUNCHPADS_QUERY)._rd;
const comb =
(rd1: { launchesPast: Launch[] }) => (rd2: { launchpads: Launchpad[] }) => {
return {
one: rd1,
two: rd2,
};
};
return match(map2(comb, RD1, RD2), {
_: () => <p>Loading...</p>,
Failure: (error) => <p>Error while fetching data ({error.message})</p>,
Success: (data) => (
<>
<p>map2</p>
{JSON.stringify(data)}
</>
),
});
Constructs a new RemoteData with a tag of Initialized. This represents a network request yet to be made.
const initialized: <T = never>() => RemoteData<T>;
Constructs a new RemoteData with a tag of Pending. This represents an in flight network request.
const pending: <T = never>() => RemoteData<T>;
Constructs a new RemoteData with a tag of Failure and an ApolloError. While Failure is usually generic in _RemoteData_, useQuery from @apollo/client represents all network failures as ApolloError. Thus, Failure is strictly typed for ApolloError.
const failure: <T = never>(error: ApolloError) => RemoteData<T>;
Constructs a new RemoteData with a tag of Success. This represents a resolved network requests with a valid response.
const success: <D = never>(data: D) => RemoteData<D>;
Returns true if the rd is an instance of Initialized, false otherwise
const isInitialized: <D = never>(rd: RemoteData<D>) => rd is Pending;
Returns true if the rd is an instance of Pending, false otherwise
const isLoading: <D = never>(rd: RemoteData<D>) => rd is Pending;
Returns true if the rd is an instance of Failure, false otherwise
const isFailure: <D = never>(rd: RemoteData<D>) => rd is Failure;
Returns true if the rd is an instance of Success, false otherwise
const isSuccess: <D = never>(rd: RemoteData<D>) => rd is Success<D>;
FAQs
A drop in replacement for apollo client's `useQuery` hook with a return type that mimics Elm's RemoteData ADT
We found that use-query-rd demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.