-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
relayStylePagination returns too many results #6792
Comments
For your backward query, you're using the variables |
Sorry, that was supposed to paginate back to repo one again. With that fixed, the idea is that looking at "repo one", and clicking <div>
<ul>
<li>
repo one
</li>
<li>
repo two
</li>
</ul>
<button>
next
</button>
<button>
previous
</button>
</div> If you remove the As soon as Thanks for looking at this. |
Ok, thanks for the update! With that out of the way, I think the next thing to explain is that the Here's another comment where I get into these details: #6729 (comment). Specifically this bit:
I dug up an older (untested!) implementation of |
@benjamn Is there any plan for the To make sure I am understanding, could you clarify for me that:
I am hoping this can be resolved in a patch sometime soon, because the Update: I have taken a stab at rewriting the helper (below), which works as I would have expected the original to. Would be interested to see your thoughts on it. There are several problems I had with the original, which I believe are solved:
Usage looks like:
type TInternalRelay<TNode> = Readonly<{
edges: Array<{
cursor: string;
node: TNode;
}>;
pageInfo: Readonly<{
hasPreviousPage: boolean;
hasNextPage: boolean;
startCursor?: string;
endCursor?: string;
}>;
}>;
interface RelayStylePaginationOptions {
usePagination?: boolean;
}
// As proof of the flexibility of field policies, this function generates
// one that handles Relay-style pagination, without Apollo Client knowing
// anything about connections, edges, cursors, or pageInfo objects.
export function relayStylePagination<TNode = Reference>(
keyArgs: KeyArgs = false,
options?: RelayStylePaginationOptions,
): FieldPolicy<TInternalRelay<TNode>> {
return {
keyArgs,
read(existing, {canRead}) {
if (!existing) return;
let edges = existing.edges.filter((edge) => canRead(edge.node));
// Note I have left the exisiting "infinite-scroll" behaviour as the default to
// avoid any breaking changes, although I strongly believe that "normal" pagination
// ought to be.
if (options?.usePagination) {
const pageInfo = existing.pageInfo;
const startIndex = edges.findIndex((edge) => edge.cursor === pageInfo?.startCursor);
if (startIndex > -1) edges = edges.slice(startIndex);
const endIndex = edges.findIndex((edge) => edge.cursor === pageInfo?.endCursor);
if (endIndex > -1) edges = edges.slice(0, endIndex + 1);
}
return {
// Some implementations return additional Connection fields, such
// as existing.totalCount. These fields are saved by the merge
// function, so the read function should also preserve them.
...existing,
edges,
};
},
merge(existing = makeEmptyData<TNode>(), incoming) {
const startCursor = incoming?.pageInfo?.startCursor;
const endCursor = incoming?.pageInfo?.endCursor;
let prefix: typeof existing.edges = [];
let suffix: typeof existing.edges = [];
// Find prefix
if (startCursor) {
const index = existing.edges.findIndex((edge) => edge.cursor === startCursor);
prefix = index > -1 ? existing.edges.slice(0, index) : existing.edges;
}
// Find suffix
if (endCursor) {
const index = existing.edges.findIndex((edge) => edge.cursor === endCursor);
suffix = index > -1 ? existing.edges.slice(index + 1) : [];
}
const edges = [...prefix, ...incoming.edges, ...suffix];
// Modify the edges ONLY.
return {
...incoming,
edges,
};
},
};
}
function makeEmptyData<TNode>(): TInternalRelay<TNode> {
return {
edges: [],
pageInfo: {
hasPreviousPage: false,
hasNextPage: false,
},
};
} |
This API change seems to make a pretty big assumption that developers won't be using traditional pagination and infinite scroll for the same query. |
Let us know if this is still a concern with |
I'm trying to write a test that paginates using the relayStylePagination function and seeing behaviour I don't understand.
Basically imagine starting with the markup below, showing "repo one", clicking
next
, seeing "repo two" and then clickingprevious
which should display "repo one" again.Clicking
next
shows both "repo two" (what I was expecting) and "repo one" (which I wasn't):If I click
previous
"repo one" is duplicated, and "repo two" is still visible:I made a codesandbox demonstrating the issue with the current version (3.1.3).
The text was updated successfully, but these errors were encountered: