Skip to content

Commit 5c0790e

Browse files
committed
Update all code samples
1 parent d84d555 commit 5c0790e

11 files changed

Lines changed: 85 additions & 53 deletions

File tree

docs/_config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ sidebar_categories:
1616
- tutorial/queries
1717
- tutorial/mutations
1818
- tutorial/local-state
19-
- tutorial/whats-next
19+
# - tutorial/whats-next
2020

2121
Resources:
2222
- resources/graphql-glossary
182 KB
Loading
520 KB
Loading

docs/source/tutorial/client.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ While Apollo Client works with any view layer, it's most commonly used with Reac
1212
For this half of the tutorial, we will be working in the `client/` folder of the project. You should have the project already from the server portioned, but if you don't, make sure to clone [the tutorial](https://github.com/apollographql/fullstack-tutorial/). From the root of the project, run:
1313

1414
```bash
15-
cd client && npm install
15+
cd start/client && npm install
1616
```
1717

1818
Now, our dependencies are installed. Here are the packages we will be using to build out our frontend:
1919

20-
- `apollo-client@next`: A complete data management solution with an intelligent cache. In this tutorial, we will be using the Apollo Client 3.0 preview since it includes local state management capabilities and sets your cache up for you.
20+
- `apollo-client@alpha`: A complete data management solution with an intelligent cache. In this tutorial, we will be using the Apollo Client 3.0 preview since it includes local state management capabilities and sets your cache up for you.
2121
- `react-apollo`: The view layer integration for React that exports components such as `Query` and `Mutation`
2222
- `graphql-tag`: The tag function `gql` that we use to wrap our query strings in order to parse them into an AST
2323

@@ -36,6 +36,12 @@ Our key is now stored under the environment variable `ENGINE_API_KEY`. Apollo VS
3636
Next, create an Apollo config file called `apollo.config.js`. This config file is how you configure both the Apollo VSCode extension and CLI. Paste the snippet below into the file:
3737

3838
```js
39+
module.exports = {
40+
client: {
41+
name: 'Space Explorer [web]',
42+
service: 'space-explorer',
43+
},
44+
};
3945
```
4046

4147
Great, we're all set up! Let's dive into building our first client.

docs/source/tutorial/data-source.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,10 @@ _src/schema.js_
6060
```graphql
6161
type Launch {
6262
id: ID!
63-
year: String
64-
mission: Mission!
63+
site: String
64+
mission: Mission
6565
rocket: Rocket
66-
launchSuccess: Boolean
67-
isBooked: Boolean
66+
isBooked: Boolean!
6867
}
6968
```
7069

@@ -77,18 +76,17 @@ launchReducer(launch) {
7776
return {
7877
id: launch.flight_number || 0,
7978
cursor: `${launch.launch_date_unix}`,
79+
site: launch.launch_site && launch.launch_site.site_name,
8080
mission: {
8181
name: launch.mission_name,
8282
missionPatchSmall: launch.links.mission_patch_small,
83-
missionPatchLarge: launch.links.mission_patch
83+
missionPatchLarge: launch.links.mission_patch,
8484
},
85-
year: launch.launch_year,
8685
rocket: {
8786
id: launch.rocket.rocket_id,
8887
name: launch.rocket.rocket_name,
8988
type: launch.rocket.rocket_type,
9089
},
91-
launchSuccess: launch.launch_success,
9290
};
9391
}
9492
```

docs/source/tutorial/introduction.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ Why do you need a graph? Today, one of the most difficult parts of building an a
2424
In this tutorial, we'll build an interactive app for reserving your spot on an upcoming Space-X launch. You can think of it as an Airbnb for space travel! All of the data is real, thanks to the [SpaceX-API](https://github.com/r-spacex/SpaceX-API).
2525

2626
Here's what the finished app will look like:
27-
<!-- TODO: Add screenshot -->
27+
28+
<div style="text-align:center">
29+
![Space explorer](../images/space-explorer.png)
30+
</div>
2831

2932
The app has five screens: a login screen, a list of launches, a launch detail, a profile page, and a cart. The graph API powering our space app connects to a REST API and a SQLite database. Don't worry if you're unfamiliar with those technologies, you don't need to know how to build a REST API or SQLite database from scratch in order to complete the tutorial.
3033

@@ -55,9 +58,11 @@ Next, in your terminal, clone this repository:
5558
git clone https://github.com/apollographql/fullstack-tutorial/
5659
```
5760

58-
There are two folders: one for the server and one for the client. We will be working in the server folder first. If you're comfortable with building a graph API already and you want to skip to the client portion, navigate to the [last half of the tutorial](./client.html).
61+
There are two folders: one for the starting point (`start/`) and one for the final version (`final`). Within each directory are two folders: one for the server and one for the client. We will be working in the server folder first. If you're comfortable with building a graph API already and you want to skip to the client portion, navigate to the [last half of the tutorial](./client.html).
5962

60-
<h3 id="vscode">Configure Apollo VSCode</h3>
63+
<!--
64+
TODO: Add in this section after Apollo VSCode works for server development
65+
<h3 id="vscode">Configure Apollo VSCode</h3> -->
6166

6267
<h3 id="help">Where can I get help?</h3>
6368

docs/source/tutorial/local-state.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ We can also add local fields to server data by extending types from our server.
4242

4343
<h2 id="store-initializers">Initialize the store</h2>
4444

45-
Now that we've created our client schema, let's learn how to initialize the store. Since queries execute as soon as the component mounts, it's important for us to warm the Apollo cache with some default state so those queries don't error out. We will need to create `storeInitializers` for both `isLoggedIn` and `cartItems` to prevent these two local queries from erroring out:
45+
Now that we've created our client schema, let's learn how to initialize the store. Since queries execute as soon as the component mounts, it's important for us to warm the Apollo cache with some default state so those queries don't error out. We will need to create `initializers` for both `isLoggedIn` and `cartItems` to prevent these two local queries from erroring out:
4646

47-
Jump to `src/index.js` and specify your `storeInitializers` on the `ApolloClient` constructor:
47+
Jump to `src/index.js` and specify your `initializers` on the `ApolloClient` constructor:
4848

4949
_src/index.js_
5050

@@ -57,14 +57,14 @@ const client = new ApolloClient({
5757
authorization: localStorage.getItem('token'),
5858
},
5959
}),
60-
storeInitializers: {
60+
initializers: {
6161
isLoggedIn: () => !!localStorage.getItem('token'),
6262
cartItems: () => [],
6363
},
6464
});
6565
```
6666

67-
These `storeInitializers` will be called as soon as `ApolloClient` is created. They will also run if the store is reset.
67+
These `initializers` will be called as soon as `ApolloClient` is created. They will also run if the store is reset.
6868

6969
Now that we've added default state to the Apollo cache, let's learn how to query local data from within our React components.
7070

@@ -138,7 +138,7 @@ export default function Cart() {
138138
<Fragment>
139139
<Header>My Cart</Header>
140140
{!data.cartItems || !data.cartItems.length ? (
141-
<p>No items in your cart</p>
141+
<p data-testid="empty-message">No items in your cart</p>
142142
) : (
143143
<Fragment>
144144
{data.cartItems.map(launchId => (
@@ -291,9 +291,11 @@ export default function BookTrips({ cartItems }) {
291291
>
292292
{(bookTrips, { data, loading, error }) =>
293293
data && data.bookTrips && !data.bookTrips.success ? (
294-
<p>{data.bookTrips.message}</p>
294+
<p data-testid="message">{data.bookTrips.message}</p>
295295
) : (
296-
<Button onClick={bookTrips}>Book All</Button>
296+
<Button onClick={bookTrips} data-testid="book-button">
297+
Book All
298+
</Button>
297299
)
298300
}
299301
</Mutation>
@@ -318,7 +320,7 @@ export const resolvers = {
318320
const { cartItems } = cache.readQuery({ query: GET_CART_ITEMS });
319321
const data = {
320322
cartItems: cartItems.includes(id)
321-
? cartItems.filter(i => !i)
323+
? cartItems.filter(i => i !== id)
322324
: [...cartItems, id],
323325
};
324326
cache.writeQuery({ query: GET_CART_ITEMS, data });
@@ -383,10 +385,17 @@ export default function ActionButton({ isBooked, id, isInCart }) {
383385
},
384386
]}
385387
>
386-
{(mutate, { data, loading, error }) => {
388+
{(mutate, { loading, error }) => {
389+
if (loading) return <p>Loading...</p>;
390+
if (error) return <p>An error occurred</p>;
391+
387392
return (
388393
<div>
389-
<Button onClick={mutate} isBooked={isBooked}>
394+
<Button
395+
onClick={mutate}
396+
isBooked={isBooked}
397+
data-testid={'action-button'}
398+
>
390399
{isBooked
391400
? 'Cancel This Trip'
392401
: isInCart

docs/source/tutorial/mutations.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ In our `onCompleted` handler, we also call `client.writeData` to write local dat
5959

6060
_src/pages/login.js_
6161

62-
```js lines=3,4,7-10,16
62+
```js lines=3,4,7-10,22
6363
export default function Login() {
6464
return (
6565
<ApolloConsumer>
@@ -71,7 +71,14 @@ export default function Login() {
7171
client.writeData({ data: { isLoggedIn: true } });
7272
}}
7373
>
74-
{(login, { data }) => <LoginForm login={login} />}
74+
{(login, { loading, error }) => {
75+
// this loading state will probably never show, but it's helpful to
76+
// have for testing
77+
if (loading) return <Loading />;
78+
if (error) return <p>An error occurred</p>;
79+
80+
return <LoginForm login={login} />;
81+
}}
7582
</Mutation>
7683
)}
7784
</ApolloConsumer>

docs/source/tutorial/queries.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,15 +330,19 @@ export default function Profile() {
330330
return (
331331
<Fragment>
332332
<Header>My Trips</Header>
333-
{data.me.trips.length ? data.me.trips.map(launch => (
334-
<LaunchTile key={launch.id} launch={launch} />
335-
)) : <p>You haven't booked any trips</p>}
333+
{data.me.trips.length ? (
334+
data.me.trips.map(launch => (
335+
<LaunchTile key={launch.id} launch={launch} />
336+
))
337+
) : (
338+
<p>You haven't booked any trips</p>
339+
)}
336340
</Fragment>
337341
);
338342
}}
339343
</Query>
340344
);
341-
};
345+
}
342346
```
343347
344348
If you try to render this query, you'll notice that it returns null. This is because we need to implement our login feature first. We're going to tackle login in the next section.

docs/source/tutorial/resolvers.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ const { paginateResults } = require('./utils');
173173
Query: {
174174
launches: async (_, { pageSize = 20, after }, { dataSources }) => {
175175
const allLaunches = await dataSources.launchAPI.getAllLaunches();
176+
// we want these in reverse chronological order
177+
allLaunches.reverse();
178+
176179
const launches = paginateResults({
177180
after,
178181
pageSize,
@@ -223,11 +226,12 @@ _src/resolvers.js_
223226

224227
```js
225228
Mission: {
226-
missionPatch: (mission, { size }) => {
229+
// make sure the default size is 'large' in case user doesn't specify
230+
missionPatch: (mission, { size } = { size: 'LARGE' }) => {
227231
return size === 'SMALL'
228232
? mission.missionPatchSmall
229233
: mission.missionPatchLarge;
230-
}
234+
},
231235
},
232236
```
233237

@@ -274,19 +278,17 @@ Let's open up `src/index.js` and update the `context` function on `ApolloServer`
274278

275279
_src/index.js_
276280

277-
```js line=4,11,15
281+
```js line=4,8,10
278282
const server = new ApolloServer({
279283
context: async ({ req }) => {
280284
// simple auth check on every request
281285
const auth = (req.headers && req.headers.authorization) || '';
282-
283286
const email = new Buffer(auth, 'base64').toString('ascii');
284287

285288
// if the email isn't formatted validly, return null for user
286289
if (!isEmail.validate(email)) return { user: null };
287-
// find a user by their email
290+
// find a user by their email
288291
const users = await store.users.findOrCreate({ where: { email } });
289-
290292
const user = users && users[0] ? users[0] : null;
291293

292294
return { user: { ...user.dataValues } };
@@ -393,6 +395,4 @@ Next, paste our authorization header into the HTTP Headers box at the bottom:
393395
}
394396
```
395397

396-
Then, run the mutation. You should see a success message, along with the ids of the mutations we just booked. Testing mutations manually in the playground is a good way to explore our API, but in a real-world application, we should run automated tests so we can safely refactor our code. In the next section, you'll learn all about testing your graph.
397-
398-
<h2 id="testing">Test your graph</h2>
398+
Then, run the mutation. You should see a success message, along with the ids of the mutations we just booked. Testing mutations manually in the playground is a good way to explore our API, but in a real-world application, we should run automated tests so we can safely refactor our code. In the next section, you'll learn all about testing your graph.

0 commit comments

Comments
 (0)