Skip to content

Commit

Permalink
Merge branch 'issue-8674-enforce-__DEV__-everywhere' into release-3.5.
Browse files Browse the repository at this point in the history
This merge of the still-open PR #8689 into `release-3.5` will allow us
to test those changes in an `@apollo/client@beta` release before merging
to `main` and releasing in v3.4.x.
  • Loading branch information
benjamn committed Aug 23, 2021
2 parents ffbddbf + 99fa6a0 commit bc15fcc
Show file tree
Hide file tree
Showing 33 changed files with 308 additions and 194 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
- Calling `refetch` on a skipped query will have no effect (issue [#8270](https://github.com/apollographql/apollo-client/issues/8270)).
- Prevent `onError` and `onCompleted` functions from firing continuously, and improving their polling behavior.

## Apollo Client 3.4.9 (not yet released)

### Bug Fixes

- Fix unhandled `Promise` rejection warnings/errors whose message is `Observable cancelled prematurely`. <br/>
[@benjamn](https://github.com/benjamn) in [#8676](https://github.com/apollographql/apollo-client/pull/8676)

- Enforce that `__DEV__` is polyfilled by every `@apollo/client/*` entry point that uses it. This build step considers not only explicit `__DEV__` usage but also `__DEV__` references injected near `invariant(...)` and `new InvariantError(...)` expressions. <br/>
[@benjamn](https://github.com/benjamn) in [#8689](https://github.com/apollographql/apollo-client/pull/8689)

## Apollo Client 3.4.8

### Bug Fixes
Expand Down
54 changes: 54 additions & 0 deletions config/checkDEV.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as path from "path";
import { readFileSync, promises as fs } from "fs";
import { eachFile, distDir } from "./helpers";

const entryPoints = require("./entryPoints.js");

const filesWithDEV = new Set<string>();

eachFile(distDir, async file => {
const source = await fs.readFile(file, "utf8");
if (/\b__DEV__\b/.test(source)) {
filesWithDEV.add(file);
}
}).then(() => {
const filesByEntryPoint = new Map<string, {
indexPath: string;
source: string;
files: Set<string>;
}>();

entryPoints.forEach(({ dirs }: { dirs: string[] }) => {
const relIndexPath = path.join(...dirs, "index.js");
const absIndexPath = path.join(distDir, relIndexPath);
filesByEntryPoint.set(dirs.join("/"), {
indexPath: relIndexPath,
source: readFileSync(absIndexPath, "utf8"),
files: new Set<string>(),
});
});

filesWithDEV.forEach(file => {
const entryPointDir = entryPoints.getEntryPointDirectory(file);
const info = filesByEntryPoint.get(entryPointDir);
const absEntryPointDir = path.join(distDir, entryPointDir);
const relPath = "./" + path.relative(absEntryPointDir, file);
if (info) {
info.files.add(relPath);
}
});

filesByEntryPoint.forEach(({ indexPath, source, files }, entryPointDir) => {
if (!files.size || source.indexOf("checkDEV()") >= 0) {
return;
}
const entryPointId = `@apollo/client/${entryPointDir}`;
throw new Error(`Entry point ${
entryPointId
}/index.js does not call checkDEV(), but ${
entryPointId
} contains the following files that use __DEV__: ${
Array.from(files).join(", ")
}`);
});
});
6 changes: 6 additions & 0 deletions config/entryPoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ function partsAfterDist(id) {
}
}

exports.getEntryPointDirectory = function (file) {
const parts = partsAfterDist(file) || file.split(path.sep);
const len = lengthOfLongestEntryPoint(parts);
if (len >= 0) return parts.slice(0, len).join(path.sep);
};

function lengthOfLongestEntryPoint(parts) {
let node = lookupTrie;
let longest = -1;
Expand Down
32 changes: 16 additions & 16 deletions docs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"dependencies": {
"gatsby": "2.32.13",
"gatsby-theme-apollo-docs": "4.7.15",
"gatsby-theme-apollo-docs": "4.7.16",
"react": "17.0.2",
"react-dom": "17.0.1",
"webpack-virtual-modules": "0.4.3"
Expand Down
2 changes: 1 addition & 1 deletion docs/source/api/link/community-links.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Thank you to all the Apollo community members who have contributed custom Apollo
| [link-http-dataloader](https://github.com/graphcool/http-link-dataloader) | [@graphcool](https://github.com/graphcool) | Batching and caching provided by dataloader. |
| [@absinthe/socket-apollo-link](https://github.com/absinthe-graphql/absinthe-socket/tree/master/packages/socket-apollo-link) | [@absinthe-graphql](https://github.com/absinthe-graphql) | Communicate over an Absinthe socket. |
| [apollo-absinthe-upload-link](https://github.com/bytewitchcraft/apollo-absinthe-upload-link) | [@bytewitchcraft](https://github.com/bytewitchcraft) | Enables file uploading to Absinthe backends. |
| [apollo-link-logger](https://github.com/blackxored/apollo-link-logger) | [@blackxored](https://github.com/blackxored) | Logger that uses similar format to redux-logger and includes performance infomation. |
| [apollo-link-logger](https://github.com/blackxored/apollo-link-logger) | [@blackxored](https://github.com/blackxored) | Logger that uses similar format to redux-logger and includes performance information. |
| [apollo-link-queue](https://github.com/helfer/apollo-link-queue) | [@helfer](https://github.com/helfer) | Buffers requests on a toggle, such as an on/offline event. |
| [apollo-link-optimistic](https://github.com/helfer/apollo-link-optimistic) | [@helfer](https://github.com/helfer) | Returns an immediate optimistic response before returning server results. |
| [apollo-link-serialize](https://github.com/helfer/apollo-link-serialize) | [@helfer](https://github.com/helfer) | Serializes requests by key to ensure execution order. |
Expand Down
62 changes: 2 additions & 60 deletions docs/source/caching/advanced-topics.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -180,67 +180,9 @@ Now whenever a query includes the `book` field, the `read` function above execut

### Incremental loading: `fetchMore`

`fetchMore` can be used to update the result of a query based on the data returned by another query. Most often, it is used to handle infinite-scroll pagination or other situations where you are loading more data when you already have some.
You can use the `fetchMore` function to update a query's cached result with data returned by a _followup_ query. Most often, `fetchMore` is used to handle infinite-scroll pagination and other situations where you're loading _more_ data when you already have _some_.

In our GitHunt example, we have a paginated feed that displays a list of GitHub repositories. When we hit the "Load More" button, we don't want Apollo Client to throw away the repository information it has already loaded. Instead, it should just append the newly loaded repositories to the list that Apollo Client already has in the store. With this update, our UI component should re-render and show us all of the available repositories.

Let's see how to do that with the `fetchMore` method on a query:

```javascript
const FEED_QUERY = gql`
query Feed($type: FeedType!, $offset: Int, $limit: Int) {
currentUser {
login
}
feed(type: $type, offset: $offset, limit: $limit) {
id
# ...
}
}
`;

const FeedWithData = ({ match }) => (
<Query
query={FEED_QUERY}
variables={{
type: match.params.type.toUpperCase() || "TOP",
offset: 0,
limit: 10
}}
fetchPolicy="cache-and-network"
>
{({ data, fetchMore }) => (
<Feed
entries={data.feed || []}
onLoadMore={() =>
fetchMore({
variables: {
offset: data.feed.length
},
updateQuery: (prev, { fetchMoreResult }) => {
if (!fetchMoreResult) return prev;
return Object.assign({}, prev, {
feed: [...prev.feed, ...fetchMoreResult.feed]
});
}
})
}
/>
)}
</Query>
);
```


The `fetchMore` method takes a map of `variables` to be sent with the new query. Here, we're setting the offset to `feed.length` so that we fetch items that aren't already displayed on the feed. This variable map is merged with the one that's been specified for the query associated with the component. This means that other variables, e.g. the `limit` variable, will have the same value as they do within the component query.

It can also take a `query` named argument, which can be a GraphQL document containing a query that will be fetched in order to fetch more information; we refer to this as the `fetchMore` query. By default, the `fetchMore` query is the query associated with the container, in this case the `FEED_QUERY`.

When we call `fetchMore`, Apollo Client will fire the `fetchMore` query and use the logic in the `updateQuery` option to incorporate that into the original result. The named argument `updateQuery` should be a function that takes the previous result of the query associated with your component (i.e. `FEED_QUERY` in this case) and the information returned by the `fetchMore` query and return a combination of the two.

Here, the `fetchMore` query is the same as the query associated with the component. Our `updateQuery` takes the new feed items returned and just appends them onto the feed items that we'd asked for previously. With this, the UI will update and the feed will contain the next page of items!

Although `fetchMore` is often used for pagination, there are many other cases in which it is applicable. For example, suppose you have a list of items (say, a collaborative todo list) and you have a way to fetch items that have been updated after a certain time. Then, you don't have to refetch the whole todo list to get updates: you can just incorporate the newly added items with `fetchMore`, as long as your `updateQuery` function correctly merges the new results.
For details, see [The `fetchMore` function](../pagination/core-api/#the-fetchmore-function).

### The `@connection` directive

Expand Down
Loading

0 comments on commit bc15fcc

Please sign in to comment.