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/7/en/part7d.md
+58-39Lines changed: 58 additions & 39 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,33 +7,70 @@ lang: en
7
7
8
8
<divclass="content">
9
9
10
-
In addition to the eight exercises in the [React Hooks](/en/part7/more_about_react_hooks) sections of this part of the course material, 15 exercises continue our work on the BlogList application that we worked on in parts four and five of the course material. Some of the following exercises are "features" that are independent of one another, meaning that there is no need to finish them in any particular order. You are free to skip over a part of the exercises if you wish to do so. Quite many of them are about applying the advanced state management technique (Zustand, React Query and context) covered in [part 6](/en/part6).
10
+
In addition to the six exercises in the [React Hooks](/en/part7/more_about_react_hooks) sections of this part of the course material, 16 exercises continue our work on the BlogList application that we worked on in parts four and five of the course material. Some of the following exercises are "features" that are independent of one another, meaning that there is no need to finish them in any particular order. You are free to skip over a part of the exercises if you wish to do so. Quite many of them are about applying the advanced state management technique (Zustand, React Query and context) covered in [part 6](/en/part6).
11
11
12
12
If you do not want to use your BlogList application, you are free to use the code from the model solution as a starting point for these exercises.
13
13
14
14
Many of the exercises in this part of the course material will require the [refactoring](https://en.wikipedia.org/wiki/Code_refactoring) of existing code. This is a common reality of extending existing applications, meaning that refactoring is an important and necessary skill even if it may feel difficult and unpleasant at times.
15
15
16
16
One good piece of advice for both refactoring and writing new code is to take <i>baby steps</i>. Losing your sanity is almost guaranteed if you leave the application in a completely broken state for long periods while refactoring.
17
17
18
+
**These exercises assume that you have already completed the exercises [5.24-5.29](/en/part5/react_router_ui_frameworks#exercises-5-24-5-29). If you have not, do those first.**
19
+
18
20
</div>
19
21
20
22
<divclass="tasks">
21
23
22
-
### Exercises 7.7.-7.21.
24
+
### Exercises 7.7.-7.22.
25
+
26
+
These exercises assume that you have already completed the exercises [5.24-5.29](/en/part5/react_router_ui_frameworks#exercises-5-24-5-29). If you have not, do those first.
23
27
24
28
#### 7.7: Frontend and backend in the same repository
25
29
26
30
During the course, the frontend and backend of the BlogList application have lived in separate repositories. A common real-world practice is to place both into a single repository, which simplifies deployment and makes it easier to share code between the two.
27
31
28
32
Read the section [Frontend and backend in the same repository](/en/part7/miscellaneous#frontend-and-backend-in-the-same-repository) from the course material and restructure your application accordingly. Place the frontend and backend source code in the same repository while keeping their <i>package.json</i> files separate.
29
33
34
+
Make sure that the development workflow still works: running <i>npm run dev</i> in the frontend directory should start the Vite dev server with hot reload as before. Also verify that the production build works: the backend should be able to serve the built frontend as a static site using a command such as <i>npm run build && npm start</i> (or equivalent scripts you define).
35
+
36
+
<i>Note:</i> if you run into strange dependency errors after reorganising the repository, the safest fix is often to delete all <i>node_modules</i> directories and run <i>npm install</i> again from scratch in each of the relevant directories.
37
+
30
38
#### 7.8: Error boundary
31
39
32
-
Errors in a React application that are not caught anywhere will result in a blank page. This is not a good user experience. Handle errors more gracefully by adding an [error boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) to your application.
40
+
Errors in a React application that are not caught anywhere will result in a blank page. This is not a good user experience. The standard React solution to this problem is the concept of an error boundary, that is a component that wraps part of the component tree and catches any rendering errors that occur within it, displaying a fallback UI instead of crashing the whole page.
41
+
42
+
Read the section [Error boundary](/en/part7/miscellaneous#error-boundary) from the course material. Then add an error boundary component to your application that catches any rendering errors and displays a user-friendly error message instead of a blank page.
43
+
44
+
The error boundary should be added to the app so that the navigation bar remains outside it. If a rendering error occurs anywhere in the rest of the application, the error boundary catches it and displays a user-friendly error message like this:
45
+
46
+

47
+
48
+
You can simulate a rendering error by temporarily throwing an exception inside one of your components, for example:
49
+
50
+
```js
51
+
constBlogList= ({ blogs }) => {
52
+
thrownewError('simulated error') /*/ highlight line
53
+
return (
54
+
// ...
55
+
)
56
+
}
57
+
```
58
+
59
+
#### 7.9: Nonexisting routes
33
60
34
-
Read the section [Error boundary](/en/part7/miscellaneous#error-boundary) from the course material. Add an error boundary component that catches any rendering errors in the app and displays a user-friendly error message instead of a blank page.
61
+
App has also another kind of error. If user tries to navigate to a non existing route such as
35
62
36
-
#### 7.9: Automatic Code Formatting
63
+

64
+
65
+
or
66
+
67
+

68
+
69
+
the result is a blank page. Fix the routing so that navigating to a non-existing path shows a proper "Page not found" message instead. React Router's [splat route](https://reactrouter.com/start/framework/routing#splats) (<i>path="*"</i>) is the right tool for this: it matches any path that no other route covers. The result should look like this:
70
+
71
+

72
+
73
+
#### 7.10: Automatic Code Formatting
37
74
38
75
In the previous parts, we used ESLint to ensure that the code follows the defined conventions. [Prettier](https://prettier.io/) is yet another approach for the same. According to the documentation, Prettier is <i>an opinionated code formatter</i>, that is, Prettier not only controls the code style but also formats the code according to the definition.
39
76
@@ -43,63 +80,63 @@ Take Prettier to use in your app and configure it to work with your editor.
43
80
44
81
### State Management: Zustand
45
82
46
-
<i>There are two alternative versions to choose for exercises 7.10-7.13: you can do the state management of the application either using Zustand or React Query and Context</i>. If you want to maximize your learning, you should do both versions!
83
+
<i>There are two alternative versions to choose for exercises 7.11-7.14: you can do the state management of the application either using Zustand or React Query and Context</i>. If you want to maximize your learning, you should do both versions!
47
84
48
85
Note: if you completed part 6 using Redux, you can of course use Redux instead of Zustand in this exercise series!
49
86
50
-
#### 7.10: Zustand, Step 1
87
+
#### 7.11: Zustand, Step 1
51
88
52
89
Refactor the application to use Zustand to manage the notification data.
53
90
54
-
#### 7.11: Zustand, Step 2
91
+
#### 7.12: Zustand, Step 2
55
92
56
93
<i>Note</i> that this and the next two exercises are quite laborious but incredibly educational.
57
94
58
95
Store the information about blog posts in the Zustand store. In this exercise, it is enough that you can see the blogs in the backend and create a new blog.
59
96
60
97
You are free to manage the state for logging in and creating new blog posts by using the internal state of React components.
61
98
62
-
#### 7.12: Zustand, Step 3
99
+
#### 7.13: Zustand, Step 3
63
100
64
101
Expand your solution so that it is again possible to like and delete a blog.
65
102
66
-
#### 7.13: Zustand, Step 4
103
+
#### 7.14: Zustand, Step 4
67
104
68
105
Store the information about the signed-in user in the Zustand store.
69
106
70
107
### State Management: React Query and Context
71
108
72
-
<i>There are two alternative versions to choose for exercises 7.10-7.13: you can do the state management of the application either using Zustand or React Query and Context</i>. If you want to maximize your learning, you should do both versions!
109
+
<i>There are two alternative versions to choose for exercises 7.11-7.14: you can do the state management of the application either using Zustand or React Query and Context</i>. If you want to maximize your learning, you should do both versions!
73
110
74
-
#### 7.10: React Query and Context step 1
111
+
#### 7.11: React Query and Context step 1
75
112
76
113
Refactor the app to use the useReducer-hook and context to manage the notification data.
77
114
78
-
#### 7.11: React Query and Context step 2
115
+
#### 7.12: React Query and Context step 2
79
116
80
117
Use React Query to manage the state for blog posts. For this exercise, it is sufficient that the application displays existing blogs and that the creation of a new blog is successful.
81
118
82
119
You are free to manage the state for logging in and creating new blog posts by using the internal state of React components.
83
120
84
-
#### 7.12: React Query and Context step 3
121
+
#### 7.13: React Query and Context step 3
85
122
86
123
Expand your solution so that it is again possible to like and delete a blog.
87
124
88
-
#### 7.13: React Query and Context step 4
125
+
#### 7.14: React Query and Context step 4
89
126
90
127
Use the useReducer-hook and context to manage the data for the logged in user.
91
128
92
129
### Views
93
130
94
131
The rest of the tasks are common to both the Zustand and React Query versions.
95
132
96
-
#### 7.14: Users view
133
+
#### 7.15: Users view
97
134
98
135
Implement a view to the application that displays all of the basic information related to users:
99
136
100
137

101
138
102
-
#### 7.15: Individual User View
139
+
#### 7.16: Individual User View
103
140
104
141
Implement a view for individual users that displays all of the blog posts added by that user:
105
142
@@ -134,25 +171,7 @@ const User = () => {
134
171
}
135
172
```
136
173
137
-
#### 7.16: Blog View
138
-
139
-
Implement a separate view for blog posts. You can model the layout of your view after the following example:
140
-
141
-

142
-
143
-
Users should be able to access this view by clicking the name of the blog post in the view that lists all of the blog posts.
144
-
145
-

146
-
147
-
After you're done with this exercise, the functionality that was implemented in exercise 5.7 is no longer necessary. Clicking a blog post no longer needs to expand the item in the list and display the details of the blog post.
0 commit comments