From 0aecf3e6fbe4fb371f4596305dc2a1cf82022f14 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Thu, 13 Jul 2023 17:58:54 +0200 Subject: [PATCH 1/5] enable renovate dependencyDashboard (#11060) --- renovate.json | 1 + 1 file changed, 1 insertion(+) diff --git a/renovate.json b/renovate.json index 0743cf096a4..abd73373f18 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,6 @@ { "extends": ["apollo-open-source"], + "dependencyDashboard": true, "pathRules": [ { "paths": ["docs/package.json"], From 4dc87954244e2c4b9249a260273d670019f0ddc0 Mon Sep 17 00:00:00 2001 From: James Pieper Date: Mon, 17 Jul 2023 10:53:57 -0500 Subject: [PATCH 2/5] Update SSR docs to use react.dev urls (#11067) --- docs/source/api/react/ssr.md | 6 +++--- docs/source/performance/server-side-rendering.mdx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/api/react/ssr.md b/docs/source/api/react/ssr.md index 7ceacb44ec4..661566b443f 100644 --- a/docs/source/api/react/ssr.md +++ b/docs/source/api/react/ssr.md @@ -24,7 +24,7 @@ import { getDataFromTree } from "@apollo/client/react/ssr"; ### Result -`getDataFromTree` returns a promise (`Promise`) which resolves when the data is ready in your Apollo Client store. The result is generated using [`ReactDOMServer.renderToStaticMarkup`](https://reactjs.org/docs/react-dom-server.html#rendertostaticmarkup) under the hood. +`getDataFromTree` returns a promise (`Promise`) which resolves when the data is ready in your Apollo Client store. The result is generated using [`ReactDOMServer.renderToStaticMarkup`](https://react.dev/reference/react-dom/server/renderToStaticMarkup) under the hood. ### Example @@ -32,7 +32,7 @@ See [Executing queries with `getDataFromTree`](../../performance/server-side-ren ## `renderToStringWithData` -The `renderToStringWithData` function is similar to `getDataFromTree`, but uses [`ReactDOMServer.renderToString`](https://reactjs.org/docs/react-dom-server.html#rendertostring) to render its result instead of [`ReactDOMServer.renderToStaticMarkup`](https://reactjs.org/docs/react-dom-server.html#rendertostaticmarkup) (the React docs help explain the difference). +The `renderToStringWithData` function is similar to `getDataFromTree`, but uses [`ReactDOMServer.renderToString`](https://react.dev/reference/react-dom/server/renderToString) to render its result instead of [`ReactDOMServer.renderToStaticMarkup`](https://react.dev/reference/react-dom/server/renderToStaticMarkup) (the React docs help explain the difference). ```js import { renderToStringWithData } from "@apollo/client/react/ssr"; @@ -46,4 +46,4 @@ import { renderToStringWithData } from "@apollo/client/react/ssr"; ### Result -`renderToStringWithData` returns a promise (`Promise`) which resolves when the data is ready in your Apollo Client store. The result is generated using [`ReactDOMServer.renderToString`](https://reactjs.org/docs/react-dom-server.html#rendertostring) under the hood. +`renderToStringWithData` returns a promise (`Promise`) which resolves when the data is ready in your Apollo Client store. The result is generated using [`ReactDOMServer.renderToString`](https://react.dev/reference/react-dom/server/renderToString) under the hood. diff --git a/docs/source/performance/server-side-rendering.mdx b/docs/source/performance/server-side-rendering.mdx index bb42f8e670a..e6e0e9ecda3 100644 --- a/docs/source/performance/server-side-rendering.mdx +++ b/docs/source/performance/server-side-rendering.mdx @@ -134,7 +134,7 @@ This function walks down the entire tree and executes every required query it en When the `Promise` resolves, you're ready to render your React tree and return it, along with the current state of the Apollo Client cache. -> Note that if you are rendering your React tree directly to a string (instead of the component-based example below), you will need to use [`renderToStringWithData`](../api/react/ssr/#rendertostringwithdata) instead of `getDataFromTree`. This will ensure the client-side React hydration works correctly by using [`ReactDOMServer.renderToString`](https://reactjs.org/docs/react-dom-server.html#rendertostring) to generate the string. +> Note that if you are rendering your React tree directly to a string (instead of the component-based example below), you will need to use [`renderToStringWithData`](../api/react/ssr/#rendertostringwithdata) instead of `getDataFromTree`. This will ensure the client-side React hydration works correctly by using [`ReactDOMServer.renderToString`](https://react.dev/reference/react-dom/server/renderToString) to generate the string. The following code replaces the `TODO` comment within the `app.use` call in the example above: From 87823ccd86b129e7a0ae8b9690dd887766ff9c0f Mon Sep 17 00:00:00 2001 From: Alessia Bellisario Date: Mon, 17 Jul 2023 14:21:34 -0400 Subject: [PATCH 3/5] chore: add note about React 18 automatic batching to useSubscription docs (#11072) --- docs/source/api/react/hooks.mdx | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/docs/source/api/react/hooks.mdx b/docs/source/api/react/hooks.mdx index 2207014952f..77c1af996e0 100644 --- a/docs/source/api/react/hooks.mdx +++ b/docs/source/api/react/hooks.mdx @@ -272,6 +272,63 @@ function DontReadTheComments({ repoFullName }) { > Refer to the [Subscriptions](../../data/subscriptions/) section for a more in-depth overview of `useSubscription`. +#### Subscriptions and React 18 Automatic Batching + +With React 18's [automatic batching](https://react.dev/blog/2022/03/29/react-v18#new-feature-automatic-batching), multiple state updates may be grouped into a single re-render for better performance. + +If your subscription API sends multiple messages at the same time or in very fast succession (within fractions of a millisecond), it is likely that only the last message received in that narrow time frame will result in a re-render. + +Consider the following component: + +```jsx +export function Subscriptions() { + const { data, error, loading } = useSubscription(query); + const [accumulatedData, setAccumulatedData] = useState([]); + + useEffect(() => { + setAccumulatedData((prev) => [...prev, data]); + }, [data]); + + return ( + <> + {loading &&

Loading...

} + {JSON.stringify(accumulatedData, undefined, 2)} + + ); +} +``` + +If your subscription back-end emits two messages with the same timestamp, only the last message received by Apollo Client will be rendered. This is because React 18 will batch these two state updates into a single re-render. + +Since the component above is using `useEffect` to push `data` into a piece of local state on each `Subscriptions` re-render, the first message will never be added to the `accumulatedData` array since its render was skipped. + +Instead of using `useEffect` here, we can re-write this component to use the `onData` callback function accepted in `useSubscription`'s `options` object: + +```jsx +export function Subscriptions() { + const [accumulatedData, setAccumulatedData] = useState([]); + const { data, error, loading } = useSubscription( + query, + { + onData({ data }) { + setAccumulatedData((prev) => [...prev, data]) + } + } + ); + + return ( + <> + {loading &&

Loading...

} + {JSON.stringify(accumulatedData, undefined, 2)} + + ); +} +``` + +> ⚠️ **Note:** The `useSubscription` option `onData` is available in Apollo Client >= 3.7. In previous versions, the equivalent option is named `onSubscriptionData`. + +Now, the first message will be added to the `accumulatedData` array since `onData` is called _before_ the component re-renders. React 18 automatic batching is still in effect and results in a single re-render, but with `onData` we can guarantee each message received after the component mounts is added to `accumulatedData`. + ### Function Signature ```ts From 1cef86dd2ac5a0b35a2a705e7ee41fbbad3468f3 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Tue, 18 Jul 2023 09:18:28 -0600 Subject: [PATCH 4/5] Update ROADMAP.md --- ROADMAP.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 6cf6f3d0275..564270d2519 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,6 +1,6 @@ # 🔮 Apollo Client Roadmap -**Last updated: 2023-06-20** +**Last updated: 2023-07-18** For up to date release notes, refer to the project's [Changelog](https://github.com/apollographql/apollo-client/blob/main/CHANGELOG.md). @@ -15,7 +15,7 @@ For up to date release notes, refer to the project's [Changelog](https://github. ## [3.8.0](https://github.com/apollographql/apollo-client/milestone/30) -_Approximate Date: GA TBD after user feedback_ +_Approximate Date: July 31, 2023_ Currently in active development and in the beta stage. React 18 users will get a lot out of this release since it introduces support for Suspense. There are also new features added to the core as well. Here's a brief overview: @@ -28,7 +28,7 @@ Currently in active development and in the beta stage. React 18 users will get - New client-side `@nonreactive` directive - A new optional `removeTypenameFromVariables` Apollo Link that will automatically strip `__typename` from your variables for each request -Try it today: `npm i @apollo/client@beta` and let us know what you think! +Try it today: `npm i @apollo/client@rc` and let us know what you think! ## [3.9.0](https://github.com/apollographql/apollo-client/milestone/32) From 50004385b3a3f99db37390ff723239b43b375ca9 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Tue, 25 Jul 2023 10:09:17 -0600 Subject: [PATCH 5/5] Update release date for 3.8 --- ROADMAP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 564270d2519..9fd2a94414d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -15,7 +15,7 @@ For up to date release notes, refer to the project's [Changelog](https://github. ## [3.8.0](https://github.com/apollographql/apollo-client/milestone/30) -_Approximate Date: July 31, 2023_ +_Approximate Date: August 7th, 2023_ Currently in active development and in the beta stage. React 18 users will get a lot out of this release since it introduces support for Suspense. There are also new features added to the core as well. Here's a brief overview: