Skip to content

Commit

Permalink
Merge pull request #79 from NerdWalletOSS/feature/useFragmentWhereName
Browse files Browse the repository at this point in the history
add support for specifying the fragment name in useFragmentWhere
  • Loading branch information
danReynolds authored Mar 26, 2024
2 parents 4628b42 + 2e1af24 commit 2d7e6c9
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 17 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
3.3.0 (Dan Reynolds)

Add support for specifying the fragment name to use in the `useFragmentWhere` API.

3.2.0 (Dan Reynolds)

Add support for an `orderBy` field to `fragmentWhere` API.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nerdwallet/apollo-cache-policies",
"version": "3.2.0",
"version": "3.3.0",
"description": "An extension to the InMemoryCache from Apollo that adds additional cache policies.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
8 changes: 6 additions & 2 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export function fieldNameFromStoreName(storeFieldName: string) {
// a leading prefix in order to distinguish it as a fragment policy and
// prevent the UUID from being trimmed by the `fieldNameFromStoreFieldName` regex.
// https://github.com/apollographql/apollo-client/blob/d9a1039d36801d450a79cb56870f0a351044254b/src/cache/inmemory/helpers.ts#L80
export function generateFragmentFieldName() {
return `-fragment-${v4()}`;
export function generateFragmentFieldName({
fragmentName,
}: {
fragmentName?: string;
} = {}) {
return `-fragment-${fragmentName ?? v4()}`;
}
22 changes: 15 additions & 7 deletions src/hooks/useFragmentTypePolicyFieldName.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import { useApolloClient } from "@apollo/client";
import { useEffect, useRef } from "react"
import { useEffect, useMemo } from "react"
import { InvalidationPolicyCache } from "../cache";
import { generateFragmentFieldName } from "../helpers";
import { usePrevious } from "./utils";

// Creates a field name to be used for a dynamically added field policy.
export const useFragmentTypePolicyFieldName = (): string => {
const { current: fieldName } = useRef(generateFragmentFieldName());
export const useFragmentTypePolicyFieldName = ({
fragmentName,
}: {
fragmentName?: string;
} = {}): string => {
const fieldName = useMemo(() => generateFragmentFieldName({ fragmentName }), [fragmentName]);
const prevFieldName = usePrevious(fieldName);
const client = useApolloClient();

useEffect(() =>
// @ts-ignore After the component using the hook is torn down, remove the dynamically added type policy
// for this hook from the type policies list.
() => delete (client.cache as InvalidationPolicyCache).policies.typePolicies.Query.fields[fieldName],
[],
() => {
// @ts-ignore After the component using the hook is torn down, remove the dynamically added type policy
// for this hook from the type policies list.
delete (client.cache as InvalidationPolicyCache).policies.typePolicies.Query.fields[prevFieldName];
},
[fieldName, prevFieldName],
);

return fieldName;
Expand Down
12 changes: 7 additions & 5 deletions src/hooks/useFragmentWhere.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { getApolloContext } from '@apollo/client';
import { useContext, useEffect, useRef } from 'react';
import { useContext, useEffect, useMemo, useRef } from 'react';
import { DocumentNode } from 'graphql';
import InvalidationPolicyCache from '../cache/InvalidationPolicyCache';
import { buildWatchFragmentWhereQuery } from '../client/utils';
import { FragmentWhereFilter, FragmentWhereOrderBy } from '../cache/types';
import { useOnce } from './utils';
import { useFragmentTypePolicyFieldName } from './useFragmentTypePolicyFieldName';
import { useGetQueryDataByFieldName } from './useGetQueryDataByFieldName';
import { makeVar } from '@apollo/client';
Expand All @@ -16,6 +15,7 @@ export default function useFragmentWhere<FragmentType>(fragment: DocumentNode, o
returnPartialData?: boolean;
limit?: number;
orderBy?: FragmentWhereOrderBy;
fragmentName?: string;
}) {
const filter = options?.filter;
const filterVarRef = useRef(makeVar<FragmentWhereFilter<FragmentType> | undefined>(filter));
Expand All @@ -32,7 +32,9 @@ export default function useFragmentWhere<FragmentType>(fragment: DocumentNode, o
const context = useContext(getApolloContext());
const client = context.client;
const cache = client?.cache as unknown as InvalidationPolicyCache;
const fieldName = useFragmentTypePolicyFieldName();
const fieldName = useFragmentTypePolicyFieldName({
fragmentName: options?.fragmentName,
});
const emptyValue = useRef<FragmentType[]>([]);

useEffect(() => {
Expand All @@ -53,7 +55,7 @@ export default function useFragmentWhere<FragmentType>(fragment: DocumentNode, o
}
}, [orderBy]);

const query = useOnce(() => buildWatchFragmentWhereQuery({
const query = useMemo(() => buildWatchFragmentWhereQuery({
filter,
filterVar,
limitVar,
Expand All @@ -62,7 +64,7 @@ export default function useFragmentWhere<FragmentType>(fragment: DocumentNode, o
fieldName,
cache,
policies: cache.policies,
}));
}), [fieldName]);

const result = useGetQueryDataByFieldName<FragmentType[]>(query, fieldName, options);

Expand Down
12 changes: 10 additions & 2 deletions src/hooks/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRef } from 'react';
import { useEffect, useRef } from 'react';
import isFunction from "lodash/isFunction";

export function useOnce<T>(value: T | (() => T)): T {
Expand All @@ -13,4 +13,12 @@ export function useOnce<T>(value: T | (() => T)): T {
hasCachedValueRef.current = true;
}
return valueRef.current as T;
}
}

export const usePrevious = <T>(value: T): T | null => {
const ref = useRef<T | null>(null);
useEffect(() => {
ref.current = value;
});
return ref.current;
};

0 comments on commit 2d7e6c9

Please sign in to comment.