Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Revamp local state tutorial chapter for AC3 #1050

Merged
merged 7 commits into from
Nov 19, 2020

Conversation

StephenBarlow
Copy link
Contributor

No description provided.

Copy link
Member

@benjamn benjamn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@StephenBarlow Really glad to see this documentation getting modernized. Feel free to take or leave any of these suggestions!

ApolloClient,
NormalizedCacheObject,
ApolloProvider,
gql // highlight-line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
gql // highlight-line
gql, // highlight-line

Do we have a style policy about trailing commas? I don't have any strong feeling; just wanted to check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't, largely because I'm not 100% clear yet on where they're desirable and where they break everything 😄

But I'll add this one!

<MultiCodeBlock>

```ts:title=src/index.tsx
const client: ApolloClient<NormalizedCacheObject> = new ApolloClient({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const client: ApolloClient<NormalizedCacheObject> = new ApolloClient({
const client = new ApolloClient({

I don't think the type parameter is necessary here? If that makes sense, you can also remove NormalizedCacheObject from the import above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit clueless on that point; this is a TypeScript sample that also auto-generates the vanilla JS sample, and my TS chops aren't sufficient to say when this typing is a good and necessary practice versus when it's superfluous 😬

Comment on lines +171 to +174
read() {
return isLoggedInVar();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this syntax, so I think we should keep it the way it is, but the following also works:

read: () => isLoggedInVar(),

However, this won't work, because the read function is called with multiple arguments:

read: isLoggedInVar,

Comment on lines 347 to 348
// Clear localStorage
localStorage.clear();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Clear localStorage
localStorage.clear();
// Remove token from localStorage
localStorage.removeItem('token');

I know you didn't add this code, but I think clearing localStorage is probably a little too aggressive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, will make corresponding change in "final" version of repo

// was just canceled.
const launch = cancelTrip.launches[0];
cache.modify({
id: `User:${localStorage.getItem('userId')}`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
id: `User:${localStorage.getItem('userId')}`,
id: cache.identify({
__typename: 'User',
id: localStorage.getItem('userId'),
}),

This avoids manual string interpolation, and reuses the same keyFields or dataIdFromObject logic that the user may have configured for the User type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I'm realizing that I need to make some changes to previous chapters to get userId stored locally again. That'll take some time tomorrow.


Our `update` function obtains the canceled trip from the mutation result, which is passed to the function. It then uses the `modify` method of `InMemoryCache` to filter that trip out of the `trips` field of our cached `User` object.

> The `cache.modify` method is a powerful and flexible tool for interacting with cached data. To learn more about it, see [`cache.modify`](https://www.apollographql.com/docs/react/caching/cache-interaction/#cachemodify)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> The `cache.modify` method is a powerful and flexible tool for interacting with cached data. To learn more about it, see [`cache.modify`](https://www.apollographql.com/docs/react/caching/cache-interaction/#cachemodify)
> The `cache.modify` method is a powerful and flexible tool for interacting with cached data. To learn more about it, see [`cache.modify`](https://www.apollographql.com/docs/react/caching/cache-interaction/#cachemodify).

Just a trailing period.

Comment on lines 535 to 562
const ToggleTripButton: React.FC<ActionButtonProps> = ({ id }) => {
const cartItems = cartItemsVar();
const isInCart = id ? cartItems.includes(id) : false;
const [, toggleTrip] = useState(isInCart);
return (
<div>
<Button
onClick={() => {
if (id) {
cartItemsVar(
isInCart
? cartItems.filter((i) => i !== id)
: [...cartItems, id]
);
// Trigger a re-render to pick up the `cartItemsVar` changes.
toggleTrip(!isInCart);
}
}}
data-testid={'action-button'}
>
{isInCart ? 'Remove from Cart' : 'Add to Cart'}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const ToggleTripButton: React.FC<ActionButtonProps> = ({ id }) => {
const cartItems = cartItemsVar();
const isInCart = id ? cartItems.includes(id) : false;
const [, toggleTrip] = useState(isInCart);
return (
<div>
<Button
onClick={() => {
if (id) {
cartItemsVar(
isInCart
? cartItems.filter((i) => i !== id)
: [...cartItems, id]
);
// Trigger a re-render to pick up the `cartItemsVar` changes.
toggleTrip(!isInCart);
}
}}
data-testid={'action-button'}
>
{isInCart ? 'Remove from Cart' : 'Add to Cart'}
const ToggleTripButton: React.FC<ActionButtonProps> = ({ id }) => {
const cartItems = useReactiveVar(cartItemsVar);
const isInCart = id ? cartItems.includes(id) : false;
return (
<div>
<Button
onClick={() => {
if (id) {
cartItemsVar(
isInCart
? cartItems.filter(itemId => itemId !== id)
: [...cartItems, id]
);
}
}}
data-testid={'action-button'}
>
{isInCart ? 'Remove from Cart' : 'Add to Cart'}

This can be a bit simpler (no need for useState) if you use useReactiveVar.

As a side note, it might be a good idea to reevaluate cartItemsVar() inside the onClick handler, so you aren't modifying a stale value. However, in this example, I don't think that causes any problems in practice.

@StephenBarlow StephenBarlow force-pushed the sb/local-state-tutorial branch from 137b299 to 8a62243 Compare November 19, 2020 01:15
@StephenBarlow StephenBarlow force-pushed the sb/local-state-tutorial branch from a86b769 to 1d00473 Compare November 19, 2020 23:46
@StephenBarlow StephenBarlow merged commit 4144b20 into master Nov 19, 2020
@StephenBarlow StephenBarlow deleted the sb/local-state-tutorial branch August 26, 2021 20:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants