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
As the linked [React page](https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key) in the error message suggests; the list items, i.e. the elements generated by the _map_ method, must each have a unique key value: an attribute called <i>key</i>.
216
+
As the linked [React page](https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key) in the error message suggests; the list items, i.e. the elements generated by the _map_ method, must each have a unique key value: an attribute called <i>key</i>.
217
217
218
218
Let's add the keys:
219
219
@@ -268,7 +268,6 @@ const notes = [
268
268
269
269
Let's pause for a moment and examine how _map_ works.
270
270
271
-
272
271
If the following code is added to, let's say, the end of the file:
273
272
274
273
```js
@@ -279,7 +278,6 @@ console.log(result)
279
278
<i>[1, 2, 3]</i> will be printed to the console.
280
279
_map_ always creates a new array, the elements of which have been created from the elements of the original array by <i>mapping</i>: using the function given as a parameter to the _map_ method.
Quite often the root of the problem is that the props are expected to be of a different type, or called with a different name than they actually are, and destructuring fails as a result. The problem often begins to solve itself when destructuring is removed and we see what the <em>props</em> contain.
540
+
Quite often the root of the problem is that the props are expected to be of a different type, or called with a different name than they actually have, and destructuring fails as a result. The problem often begins to solve itself when destructuring is removed and we see what the <em>props</em> contain.
Copy file name to clipboardExpand all lines: src/content/2/en/part2b.md
+8-10Lines changed: 8 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -401,7 +401,7 @@ You can find the code for our current application in its entirety in the <i>part
401
401
402
402
In the first exercise, we will start working on an application that will be further developed in the later exercises. In related sets of exercises, it is sufficient to return the final version of your application. You may also make a separate commit after you have finished each part of the exercise set, but doing so is not required.
403
403
404
-
<h4>2.6: The Phonebook Step1</h4>
404
+
<h4>2.6: The Phonebook Step 1</h4>
405
405
406
406
Let's create a simple phonebook. <i>**In this part, we will only be adding names to the phonebook.**</i>
407
407
@@ -459,13 +459,13 @@ Note the use of the React developer tools extension in the picture above!
459
459
- you can use the person's name as a value of the <i>key</i> property
460
460
- remember to prevent the default action of submitting HTML forms!
461
461
462
-
<h4>2.7: The Phonebook Step2</h4>
462
+
<h4>2.7: The Phonebook Step 2</h4>
463
463
464
464
Prevent the user from being able to add names that already exist in the phonebook. JavaScript arrays have numerous suitable [methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) for accomplishing this task. Keep in mind [how object equality works](https://www.joshbritz.co/posts/why-its-so-hard-to-check-object-equality/) in Javascript.
465
465
466
466
Issue a warning with the [alert](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert) command when such an action is attempted:
467
467
468
-

468
+

469
469
470
470
**Hint:** when you are forming strings that contain values from variables, it is recommended to use a [template string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals):
471
471
@@ -487,7 +487,7 @@ newName + ' is already added to phonebook'
487
487
488
488
Using template strings is the more idiomatic option and the sign of a true JavaScript professional.
489
489
490
-
<h4>2.8: The Phonebook Step3</h4>
490
+
<h4>2.8: The Phonebook Step 3</h4>
491
491
492
492
Expand your application by allowing users to add phone numbers to the phone book. You will need to add a second <i>input</i> element to the form (along with its own event handler):
493
493
@@ -503,11 +503,11 @@ At this point, the application could look something like this. The image also di
503
503
504
504

505
505
506
-
<h4>2.9*: The Phonebook Step4</h4>
506
+
<h4>2.9*: The Phonebook Step 4</h4>
507
507
508
508
Implement a search field that can be used to filter the list of people by name:
509
509
510
-

510
+

511
511
512
512
You can implement the search field as an <i>input</i> element that is placed outside the HTML form. The filtering logic shown in the image is <i>case insensitive</i>, meaning that the search term <i>arto</i> also returns results that contain Arto with an uppercase A.
513
513
@@ -528,7 +528,7 @@ const App = () => {
528
528
529
529
This saves you from having to manually input data into your application for testing out your new functionality.
530
530
531
-
<h4>2.10: The Phonebook Step5</h4>
531
+
<h4>2.10: The Phonebook Step 5</h4>
532
532
533
533
If you have implemented your application in a single component, refactor it by extracting suitable parts into new components. Maintain the application's state and all event handlers in the <i>App</i> root component.
534
534
@@ -560,8 +560,6 @@ const App = () => {
560
560
}
561
561
```
562
562
563
-
**NB**: You might run into problems in this exercise if you define your components "in the wrong place". Now would be a good time to rehearse
564
-
the chapter [do not define a component in another component](/en/part1/a_more_complex_state_debugging_react_apps#do-not-define-components-within-components)
565
-
from the last part.
563
+
**NB**: You might run into problems in this exercise if you define your components "in the wrong place". Now would be a good time to rehearse the chapter [do not define a component in another component](/en/part1/a_more_complex_state_debugging_react_apps#do-not-define-components-within-components) from the last part.
Copy file name to clipboardExpand all lines: src/content/2/en/part2c.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -43,15 +43,15 @@ After installing run the following command to run the json-server. The <i>json-s
43
43
json-server --port 3001--watch db.json
44
44
```
45
45
46
-
However, a global installation is not necessary. From the root directory of your app, we can run the <i>json-server</i> using the command _npx_:
46
+
However, a global installation is not necessary. From the root directory of your app, we can run the <i>json-server</i> using the command _npx_:
47
47
48
48
```js
49
49
npx json-server --port 3001--watch db.json
50
50
```
51
51
52
52
Let's navigate to the address <http://localhost:3001/notes> in the browser. We can see that <i>json-server</i> serves the notes we previously wrote to the file in JSON format:
53
53
54
-

54
+

55
55
56
56
If your browser doesn't have a way to format the display of JSON-data, then install an appropriate plugin, e.g. [JSONVue](https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc) to make your life easier.
57
57
@@ -139,7 +139,7 @@ We could use the previously mentioned promise-based function [fetch](https://dev
139
139
140
140
That being said, we will be using the [axios](https://github.com/axios/axios) library instead for communication between the browser and server. It functions like fetch but is somewhat more pleasant to use. Another good reason to use axios is our getting familiar with adding external libraries, so-called <i>npm packages</i>, to React projects.
141
141
142
-
Nowadays, practically all JavaScript projects are defined using the node package manager, aka [npm](https://docs.npmjs.com/getting-started/what-is-npm). The projects created using Vite also follow the npm format. A clear indicator that a project uses npm is the <i>package.json</i> file located at the root of the project:
142
+
Nowadays, practically all JavaScript projects are defined using the node package manager, aka [npm](https://docs.npmjs.com/about-npm). The projects created using Vite also follow the npm format. A clear indicator that a project uses npm is the <i>package.json</i> file located at the root of the project:
143
143
144
144
```json
145
145
{
@@ -352,10 +352,10 @@ What's not immediately obvious, however, is where the command <em>axios.get</em>
352
352
353
353
### Effect-hooks
354
354
355
-
We have already used [state hooks](https://react.dev/learn/state-a-components-memory) that were introduced along with React version [16.8.0](https://www.npmjs.com/package/react/v/16.8.0), which provide state to React components defined as functions - the so-called <i>functional components</i>. Version 16.8.0 also introduces [effect hooks](https://react.dev/reference/react#effect-hooks) as a new feature. As per the official docs:
355
+
We have already used [state hooks](https://react.dev/learn/state-a-components-memory) that were introduced along with React version [16.8.0](https://www.npmjs.com/package/react/v/16.8.0), which provide state to React components defined as functions - the so-called <i>functional components</i>. Version 16.8.0 also introduces [effect hooks](https://react.dev/reference/react/hooks#effect-hooks) as a new feature. As per the official docs:
356
356
357
-
> <i>The Effect Hook lets you perform side effects on function components.</i>
358
-
> <i>Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects.</i>
357
+
> <i>Effects let a component connect to and synchronize with external systems.</i>
358
+
> <i>This includes dealing with network, browser DOM, animations, widgets written using a different UI library, and other non-React code.</i>
359
359
360
360
As such, effect hooks are precisely the right tool to use when fetching data from a server.
361
361
@@ -531,7 +531,7 @@ At this point in development, all the parts of the application happen to reside
531
531
532
532
<h3>Exercise 2.11.</h3>
533
533
534
-
<h4>2.11: The Phonebook Step6</h4>
534
+
<h4>2.11: The Phonebook Step 6</h4>
535
535
536
536
We continue with developing the phonebook. Store the initial state of the application in the file <i>db.json</i>, which should be placed in the root of the project.
Copy file name to clipboardExpand all lines: src/content/2/en/part2d.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,7 @@ When creating notes in our application, we would naturally want to store them in
13
13
14
14
The json-server does not exactly match the description provided by the textbook [definition](https://en.wikipedia.org/wiki/Representational_state_transfer) of a REST API, but neither do most other APIs claiming to be RESTful.
15
15
16
-
We will take a closer look at REST in the [next part](/en/part3) of the course. But it's important to familiarize ourselves at this point with some of the [conventions](https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services) used by json-server and REST APIs in general. In particular, we will be taking a look at the conventional use of [routes](https://github.com/typicode/json-server#routes), aka URLs and HTTP request types, in REST.
16
+
We will take a closer look at REST in the [next part](/en/part3) of the course. But it's important to familiarize ourselves at this point with some of the [conventions](https://en.wikipedia.org/wiki/REST#Applied_to_web_services) used by json-server and REST APIs in general. In particular, we will be taking a look at the conventional use of [routes](https://github.com/typicode/json-server#routes), aka URLs and HTTP request types, in REST.
17
17
18
18
### REST
19
19
@@ -73,7 +73,7 @@ Also the tab <i>response</i> is useful, it shows what was the data the server re
73
73
74
74

75
75
76
-
The new note is not rendered to the screen yet. This is because we did not update the state of the <i>App</i> component when we created the new note. Let's fix this:
76
+
The new note is not rendered to the screen yet. This is because we did not update the state of the <i>App</i> component when we created it. Let's fix this:
77
77
78
78
```js
79
79
addNote=event=> {
@@ -706,25 +706,25 @@ Full stack development is <i> extremely hard</i>, that is why I will use all the
706
706
- I will progress with small steps
707
707
- I will write lots of _console.log_ statements to make sure I understand how the code behaves and to help pinpoint problems
708
708
- If my code does not work, I will not write more code. Instead, I start deleting the code until it works or just return to a state when everything was still working
709
-
- When I ask for help in the course Discord or Telegram channel or elsewhere I formulate my questions properly, see [here](https://fullstackopen.com/en/part0/general_info#how-to-get-help-in-discord-telegram) how to ask for help
709
+
- When I ask for help in the course Discord or Telegram channel or elsewhere I formulate my questions properly, see [here](/en/part0/general_info#how-to-get-help-in-discord-telegram) how to ask for help
710
710
711
711
</div>
712
712
713
713
<div class="tasks">
714
714
715
715
<h3>Exercises 2.12.-2.15.</h3>
716
716
717
-
<h4>2.12: The Phonebook step7</h4>
717
+
<h4>2.12: The Phonebook step 7</h4>
718
718
719
719
Let's return to our phonebook application.
720
720
721
721
Currently, the numbers that are added to the phonebook are not saved to a backend server. Fix this situation.
722
722
723
-
<h4>2.13: The Phonebook step8</h4>
723
+
<h4>2.13: The Phonebook step 8</h4>
724
724
725
725
Extract the code that handles the communication with the backend into its own module by following the example shown earlier in this part of the course material.
726
726
727
-
<h4>2.14: The Phonebook step9</h4>
727
+
<h4>2.14: The Phonebook step 9</h4>
728
728
729
729
Make it possible for users to delete entries from the phonebook. The deletion can be done through a dedicated button for each person in the phonebook list. You can confirm the action from the user by using the [window.confirm](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) method:
730
730
@@ -743,7 +743,7 @@ const delete = (id) => {
743
743
}
744
744
```
745
745
746
-
<h4>2.15*: The Phonebook step10</h4>
746
+
<h4>2.15*: The Phonebook step 10</h4>
747
747
748
748
<i>Why is there a star in the exercise? See [here](/en/part0/general_info#taking-the-course) for the explanation.</i>
Copy file name to clipboardExpand all lines: src/content/2/en/part2e.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -243,7 +243,7 @@ const Footer = () => {
243
243
return (
244
244
<div style={footerStyle}>
245
245
<br />
246
-
<em>Note app, Department of Computer Science, University of Helsinki 2023</em>
246
+
<em>Note app, Department of Computer Science, University of Helsinki 2024</em>
247
247
</div>
248
248
)
249
249
}
@@ -282,15 +282,15 @@ The code of the final version of our application can be found in the <i>part2-8
282
282
283
283
<h3>Exercises 2.16.-2.17.</h3>
284
284
285
-
<h4>2.16: Phonebook step11</h4>
285
+
<h4>2.16: Phonebook step 11</h4>
286
286
287
287
Use the [improved error message](/en/part2/adding_styles_to_react_app#improved-error-message) example from part 2 as a guide to show a notification that lasts for a few seconds after a successful operation is executed (a person is added or a number is changed):
288
288
289
289

290
290
291
-
<h4>2.17*: Phonebook step12</h4>
291
+
<h4>2.17*: Phonebook step 12</h4>
292
292
293
-
Open your application in two browsers. **If you delete a person in browser 1** a short while before attempting to <i>change the person's phone number</i> in browser 2, you will get the following 2 error messages:
293
+
Open your application in two browsers. **If you delete a person in browser 1** a short while before attempting to <i>change the person's phone number</i> in browser 2, you will get the following error messages:
294
294
295
295

296
296
@@ -383,7 +383,7 @@ const App = () => {
383
383
// ...
384
384
```
385
385
386
-
on the first render the following code gets executed
386
+
on the first render the following code gets executed:
387
387
388
388
```js
389
389
notesToShow = notes
@@ -565,7 +565,7 @@ However, there are situations where that technique would not work. For example,
565
565
566
566
<h3>Exercises 2.18.-2.20.</h3>
567
567
568
-
<h4>2.18* Data for countries, step1</h4>
568
+
<h4>2.18* Data for countries, step 1</h4>
569
569
570
570
At [https://studies.cs.helsinki.fi/restcountries/](https://studies.cs.helsinki.fi/restcountries/) you can find a service that offers a lot of information related to different countries in a so-called machine-readable format via the REST API. Make an application that allows you to view information from different countries.
571
571
@@ -585,7 +585,7 @@ When there is only one country matching the query, then the basic data of the co
585
585
586
586
**NB**: It is enough that your application works for most countries. Some countries, like <i>Sudan</i>, can be hard to support since the name of the country is part of the name of another country, <i>South Sudan</i>. You don't need to worry about these edge cases.
587
587
588
-
<h4>2.19*: Data for countries, step2</h4>
588
+
<h4>2.19*: Data for countries, step 2</h4>
589
589
590
590
**There is still a lot to do in this part, so don't get stuck on this exercise!**
Copy file name to clipboardExpand all lines: src/content/2/es/part2.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,6 @@ lang: es
8
8
9
9
Continuemos nuestra introducción a React. Primero, veremos cómo representar una colección de datos, como una lista de nombres, en la pantalla. Después de esto, inspeccionaremos cómo un usuario puede enviar datos a una aplicación React utilizando formularios HTML. A continuación, nuestro enfoque se centra en ver cómo el código JavaScript en el navegador puede obtener y manejar los datos almacenados en un servidor backend remoto. Por último, echaremos un vistazo rápido a algunas formas sencillas de agregar estilos CSS a nuestras aplicaciones React.
10
10
11
-
<i>Parte actualizada el 18 de enero de 2023</i>
12
-
- <i>Numeración de ejercicios actualizada, los ejercicios 2.11-13 fueron movidos al final de la parte</i>
0 commit comments