You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/0/en/part0a.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,6 +17,8 @@ Participants are expected to have good programming skills, basic knowledge of we
17
17
18
18
Previous knowledge of JavaScript or other course topics is not required.
19
19
20
+
How much programming experience is needed? It is hard to say, but you should be pretty fluent with <i>your</i> language. This level of fluency takes usually at least 100-200 of hours practice to develop.
21
+
20
22
### Course material
21
23
22
24
The course material is meant to be read one part at a time and in order.
Laajenna filtteriä siten, että se etsii hakusanaa kentistä <i>title</i> ja <i>author</i>, eli
992
992
993
-
_GET /api/blogs?serch=jami_ palauttaa ne blogit joiden kentässä <i>title</i> tai kentässä <i>author</i> esiintyy hakusana <i>jami</i>
993
+
_GET /api/blogs?search=jami_ palauttaa ne blogit joiden kentässä <i>title</i> tai kentässä <i>author</i> esiintyy hakusana <i>jami</i>
994
994
#### Tehtävä 13.15.
995
995
996
996
Muokkaa blogien reittiä siten, että se palauttaa blogit tykkäysten perusteella laskevassa järjestyksessä. Etsi [dokumentaatiosta](https://sequelize.org/master/manual/model-querying-basics.html) ohjeet järjestämiselle.
Copy file name to clipboardExpand all lines: src/content/2/fi/osa2d.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -694,7 +694,7 @@ Sovelluksen tämänhetkinen koodi on kokonaisuudessaan [GitHubissa](https://gith
694
694
695
695
On taas tehtävien aika. Tehtävien haastavuus alkaa nousta, sillä koodin toimivuuteen vaikuttaa myös se, kommunikoiko React-koodi oikein JSON Serverin kanssa.
696
696
697
-
Meidän onkin syytä päivittää websovelluskehittäjän vala <i>Full stack -sovelluskehittäjän valaksi</i>, eli muistuttaa itseämme siitä, että frontendin koodin lisäksi seuraamme koko ajan sitä, miten fronend ja backend kommunikoivat.
697
+
Meidän onkin syytä päivittää websovelluskehittäjän vala <i>Full stack -sovelluskehittäjän valaksi</i>, eli muistuttaa itseämme siitä, että frontendin koodin lisäksi seuraamme koko ajan sitä, miten frontend ja backend kommunikoivat.
698
698
699
699
Full stack -ohjelmointi on <i>todella</i> hankalaa, ja sen takia lupaan hyödyntää kaikkia ohjelmointia helpottavia keinoja:
Copy file name to clipboardExpand all lines: src/content/6/en/part6a.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ lang: en
7
7
8
8
<divclass="content">
9
9
10
-
So far, we have followed the state management conventions recommended by React. We have placed the state and the functions for handling it in [higher level](https://reactjs.org/docs/lifting-state-up.html) of the component structyre of the application. Quite often most of the app state and state altering functions reside rirectly in the root component. The state and its handler methods have then been passed to other components with props. This works up to a certain point, but when applications grow larger, state management becomes challenging.
10
+
So far, we have followed the state management conventions recommended by React. We have placed the state and the functions for handling it in [higher level](https://reactjs.org/docs/lifting-state-up.html) of the component structure of the application. Quite often most of the app state and state altering functions reside directly in the root component. The state and its handler methods have then been passed to other components with props. This works up to a certain point, but when applications grow larger, state management becomes challenging.
Copy file name to clipboardExpand all lines: src/content/8/en/part8a.md
+21-35Lines changed: 21 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -250,17 +250,17 @@ Let's implement a GraphQL server with today's leading library: [Apollo Server](h
250
250
Create a new npm project with _npm init_ and install the required dependencies.
251
251
252
252
```bash
253
-
npm install apollo-server@3.10.1 graphql
253
+
npm install @apollo/server graphql
254
254
```
255
255
256
-
**Note** at the time of writing (10th Dec 2022) the code used in this part is not fully compatible with the new version of the Apollo Server, and because of this, if you want everything to work smoothly you should install the version _3.10.1_. Material shall be updated to use the most recent Apollo Server in early 2023.
257
256
258
257
Also create a `index.js` file in your project's root directory.
@@ -315,12 +315,14 @@ const server = new ApolloServer({
315
315
resolvers,
316
316
})
317
317
318
-
server.listen().then(({ url }) => {
318
+
startStandaloneServer(server, {
319
+
listen: { port:4000 },
320
+
}).then(({ url }) => {
319
321
console.log(`Server ready at ${url}`)
320
322
})
321
323
```
322
324
323
-
The heart of the code is an _ApolloServer_, which is given two parameters:
325
+
The heart of the code is an [ApolloServer](https://www.apollographql.com/docs/apollo-server/api/apollo-server/), which is given two parameters:
324
326
325
327
```js
326
328
constserver=newApolloServer({
@@ -331,7 +333,7 @@ const server = new ApolloServer({
331
333
332
334
The first parameter, _typeDefs_, contains the GraphQL schema.
333
335
334
-
The second parameter is an object, which contains the [resolvers](https://www.apollographql.com/tutorials/fullstack-quickstart/04-writing-query-resolvers) of the server. These are the code, which defines <i>how</i> GraphQL queries are responded to.
336
+
The second parameter is an object, which contains the [resolvers](https://www.apollographql.com/docs/apollo-server/data/resolvers/) of the server. These are the code, which defines <i>how</i> GraphQL queries are responded to.
335
337
336
338
The code of the resolvers is the following:
337
339
@@ -426,13 +428,10 @@ The second parameter, _args_, contains the parameters of the query.
426
428
The resolver then returns from the array _persons_ the person whose name is the same as the value of <i>args.name</i>.
427
429
The resolver does not need the first parameter _root_.
428
430
429
-
430
-
431
-
In fact, all resolver functions are given [four parameters](https://www.graphql-tools.com/docs/resolvers#resolver-function-signature). With JavaScript, the parameters don't have to be defined if they are not needed. We will be using the first and the third parameter of a resolver later in this part.
431
+
In fact, all resolver functions are given [four parameters](https://www.graphql-tools.com/docs/resolvers#resolver-function-signature). With JavaScript, the parameters don't have to be defined if they are not needed. We will be using the first and the third parameter of a resolver later in this part.
432
432
433
433
### The default resolver
434
434
435
-
436
435
When we do a query, for example
437
436
438
437
```js
@@ -453,7 +452,6 @@ We have so far only defined resolvers for fields of the type <i>Query</i>, so fo
453
452
Because we did not define resolvers for the fields of the type <i>Person</i>, Apollo has defined [default resolvers](https://www.graphql-tools.com/docs/resolvers/#default-resolver) for them.
454
453
They work like the one shown below:
455
454
456
-
457
455
```js
458
456
constresolvers= {
459
457
Query: {
@@ -473,13 +471,10 @@ const resolvers = {
473
471
}
474
472
```
475
473
476
-
477
474
The default resolver returns the value of the corresponding field of the object. The object itself can be accessed through the first parameter of the resolver, _root_.
478
475
479
-
480
476
If the functionality of the default resolver is enough, you don't need to define your own. It is also possible to define resolvers for only some fields of a type, and let the default resolvers handle the rest.
481
477
482
-
483
478
We could for example define that the address of all persons is
484
479
<i>Manhattan New York</i> by hard-coding the following to the resolvers of the street and city fields of the type <i>Person</i>:
485
480
@@ -516,10 +511,8 @@ type Query {
516
511
}
517
512
```
518
513
519
-
520
514
so a person now has a field with the type <i>Address</i>, which contains the street and the city.
521
515
522
-
523
516
The queries requiring the address change into
524
517
525
518
```js
@@ -565,7 +558,6 @@ let persons = [
565
558
]
566
559
```
567
560
568
-
569
561
The person-objects saved in the server are not exactly the same as the GraphQL type <i>Person</i> objects described in the schema.
570
562
571
563
Contrary to the <i>Person</i> type, the <i>Address</i> type does not have an <i>id</i> field, because they are not saved into their own separate data structure in the server.
@@ -615,10 +607,8 @@ type Mutation {
615
607
}
616
608
```
617
609
618
-
619
610
The Mutation is given the details of the person as parameters. The parameter <i>phone</i> is the only one which is nullable. The Mutation also has a return value. The return value is type <i>Person</i>, the idea being that the details of the added person are returned if the operation is successful and if not, null. Value for the field <i>id</i> is not given as a parameter. Generating an id is better left for the server.
620
611
621
-
622
612
Mutations also require a resolver:
623
613
624
614
```js
@@ -707,14 +697,13 @@ If we try to create a new person, but the parameters do not correspond with the
707
697
708
698
So some of the error handling can be automatically done with GraphQL [validation](https://graphql.org/learn/validation/).
709
699
710
-
However, GraphQL cannot handle everything automatically. For example, stricter rules for data sent to a Mutation have to be added manually.
711
-
The errors from those rules are handled by [the error handling mechanism of Apollo Server](https://www.apollographql.com/docs/apollo-server/data/errors).
700
+
However, GraphQL cannot handle everything automatically. For example, stricter rules for data sent to a Mutation have to be added manually. An error could be handeled by throwing [GraphQLError](https://www.apollographql.com/docs/apollo-server/data/errors/#custom-errors) with a proper
So if the name to be added already exists in the phonebook, throw _UserInputError_ error.
734
+
So if the name to be added already exists in the phonebook, throw _GraphQLError_ error.
743
735
744
-

736
+

745
737
746
738
The current code of the application can be found on [GitHub](https://github.com/fullstack-hy2020/graphql-phonebook-backend/tree/part8-2), branch <i>part8-2</i>.
747
739
@@ -933,12 +925,6 @@ In some cases, it might be beneficial to name the queries. This is the case espe
933
925
Through the exercises, we will implement a GraphQL backend for a small library.
934
926
Start with [this file](https://github.com/fullstack-hy2020/misc/blob/master/library-backend.js). Remember to _npm init_ and to install dependencies!
935
927
936
-
**Note** at the time of writing (10th Dec 2022) the code used in this part is not fully compatible with the new version of the Apollo Server, and because of this, if you want everything to work smoothly you should install the version _3.10.1_:
<!-- Renderöidään mahdollinen virheilmoitus näytölle -->
616
+
We have to dig quite deep to the error object until we find the proper error messages...
617
+
620
618
We can then render the error message on the screen as necessary:
621
619
622
620
```js
@@ -750,8 +748,6 @@ It looks bleak, but it works:
750
748
Surprisingly, when a person's number is changed, the new number automatically appears on the list of persons rendered by the <i>Persons</i> component.
751
749
This happens because each person has an identifying field of type <i>ID</i>, so the person's details saved to the cache update automatically when they are changed with the mutation.
752
750
753
-
The current code of the application can be found on [GitHub](https://github.com/fullstack-hy2020/graphql-phonebook-frontend/tree/part8-4) branch <i>part8-4</i>.
754
-
755
751
Our application still has one small flaw. If we try to change the phone number for a name which does not exist, nothing seems to happen.
756
752
This happens because if a person with the given name cannot be found,
757
753
the mutation response is <i>null</i>:
@@ -820,7 +816,7 @@ useEffect(() => {
820
816
821
817
However, this solution does not work if the _notify_ function is not wrapped to a [useCallback](https://reactjs.org/docs/hooks-reference.html#usecallback) function. If it's not, this results in an endless loop. When the _App_ component is rerendered after a notification is removed, a <i>new version</i> of _notify_ gets created which causes the effect function to be executed, which causes a new notification, and so on, and so on...
822
818
823
-
The current code of the application can be found on [GitHub](https://github.com/fullstack-hy2020/graphql-phonebook-frontend/tree/part8-5) branch <i>part8-5</i>.
819
+
The current code of the application can be found on [GitHub](https://github.com/fullstack-hy2020/graphql-phonebook-frontend/tree/part8-4) branch <i>part8-4</i>.
0 commit comments