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
Create a new create-react-app-application and install </i>redux</i> with the command
36
+
Create a new Vite application and install </i>redux</i> with the command
37
37
38
38
```bash
39
39
npm install redux
@@ -175,7 +175,7 @@ would cause the following to be printed
175
175
-1
176
176
</pre>
177
177
178
-
The code of our counter application is the following. All of the code has been written in the same file (_index.js_), so <i>store</i> is directly available for the React code. We will get to know better ways to structure React/Redux code later.
178
+
The code of our counter application is the following. All of the code has been written in the same file (_main.jsx_), so <i>store</i> is directly available for the React code. We will get to know better ways to structure React/Redux code later.
179
179
180
180
```js
181
181
importReactfrom'react'
@@ -374,8 +374,55 @@ Let's expand our reducer so that it can handle the change of a note's importance
374
374
}
375
375
```
376
376
377
-
Since we do not have any code which uses this functionality yet, we are expanding the reducer in the 'test-driven' way.
378
-
Let's start by creating a test for handling the action <i>NEW\_NOTE</i>.
377
+
Since we do not have any code which uses this functionality yet, we are expanding the reducer in the 'test-driven' way. Let's start by creating a test for handling the action <i>NEW\_NOTE</i>.
378
+
379
+
We have to first configure the [Jest](https://jestjs.io/) testing library for the project. Let us install the following dependencies:
380
+
381
+
```js
382
+
npm install --save-dev jest @babel/preset-env @babel/preset-react eslint-plugin-jest
383
+
```
384
+
385
+
Next we'll create the file <i>.babelrc</i>, with the following content:
And finally, <i>.eslintrc.cjs</i> needs to be altered as follows:
413
+
414
+
```js
415
+
module.exports= {
416
+
root:true,
417
+
env: {
418
+
browser:true,
419
+
es2020:true,
420
+
"jest/globals":true// highlight-line
421
+
},
422
+
// ...
423
+
}
424
+
```
425
+
379
426
380
427
To make testing easier, we'll first move the reducer's code to its own module to file <i>src/reducers/noteReducer.js</i>. We'll also add the library [deep-freeze](https://www.npmjs.com/package/deep-freeze), which can be used to ensure that the reducer has been correctly defined as an immutable function.
381
428
Let's install the library as a development dependency
@@ -854,9 +901,9 @@ First, we install react-redux
854
901
npm install react-redux
855
902
```
856
903
857
-
Next, we move the _App_ component into its own file _App.js_. Let's see how this affects the rest of the application files.
904
+
Next, we move the _App_ component into its own file _App.jsx_. Let's see how this affects the rest of the application files.
858
905
859
-
_index.js_ becomes:
906
+
_main.jsx_ becomes:
860
907
861
908
```js
862
909
importReactfrom'react'
@@ -1008,8 +1055,7 @@ const App = () => {
1008
1055
}
1009
1056
```
1010
1057
1011
-
The <i>useDispatch</i> hook provides any React component access to the dispatch function of the Redux store defined in <i>index.js</i>.
1012
-
This allows all components to make changes to the state of the Redux store.
1058
+
The <i>useDispatch</i> hook provides any React component access to the dispatch function of the Redux store defined in <i>main.jsx</i>. This allows all components to make changes to the state of the Redux store.
1013
1059
1014
1060
The component can access the notes stored in the store with the [useSelector](https://react-redux.js.org/api/hooks#useselector)-hook of the react-redux library.
1015
1061
@@ -1078,7 +1124,7 @@ export default NewNote
1078
1124
1079
1125
Unlike in the React code we did without Redux, the event handler for changing the state of the app (which now lives in Redux) has been moved away from the <i>App</i> to a child component. The logic for changing the state in Redux is still neatly separated from the whole React part of the application.
1080
1126
1081
-
We'll also separate the list of notes and displaying a single note into their own components (which will both be placed in the <i>Notes.js</i> file ):
1127
+
We'll also separate the list of notes and displaying a single note into their own components (which will both be placed in the <i>Notes.jsx</i> file ):
Copy file name to clipboardExpand all lines: src/content/6/en/part6b.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
@@ -7,7 +7,7 @@ lang: en
7
7
8
8
<divclass="content">
9
9
10
-
Let's continue our work with the simplified [redux version](/en/part6/flux_architecture_and_redux#redux-notes) of our notes application.
10
+
Let's continue our work with the simplified [Redux version](/en/part6/flux_architecture_and_redux#redux-notes) of our notes application.
11
11
12
12
To ease our development, let's change our reducer so that the store gets initialized with a state that contains a couple of notes:
13
13
@@ -132,7 +132,7 @@ export default filterReducer
132
132
133
133
We can create the actual reducer for our application by combining the two existing reducers with the [combineReducers](https://redux.js.org/api/combinereducers) function.
134
134
135
-
Let's define the combined reducer in the <i>index.js</i> file:
135
+
Let's define the combined reducer in the <i>main.jsx</i> file:
The state of the store defined by the reducer above is an object with two properties: <i>notes</i> and <i>filter</i>. The value of the <i>notes</i> property is defined by the <i>noteReducer</i>, which does not have to deal with the other properties of the state. Likewise, the <i>filter</i> property is managed by the <i>filterReducer</i>.
190
190
191
-
Before we make more changes to the code, let's take a look at how different actions change the state of the store defined by the combined reducer. Let's add the following to the <i>index.js</i> file:
191
+
Before we make more changes to the code, let's take a look at how different actions change the state of the store defined by the combined reducer. Let's add the following to the <i>main.jsx</i> file:
@@ -220,7 +220,7 @@ Is there a bug in our code? No. The combined reducer works in such a way that ev
220
220
221
221
### Finishing the filters
222
222
223
-
Let's finish the application so that it uses the combined reducer. We start by changing the rendering of the application and hooking up the store to the application in the <i>index.js</i> file:
223
+
Let's finish the application so that it uses the combined reducer. We start by changing the rendering of the application and hooking up the store to the application in the <i>main.jsx</i> file:
@@ -430,7 +430,7 @@ Let's start using Redux Toolkit in our application by refactoring the existing c
430
430
npm install @reduxjs/toolkit
431
431
```
432
432
433
-
Next, open the <i>index.js</i> file which currently creates the Redux store. Instead of Redux's <em>createStore</em> function, let's create the store using Redux Toolkit's [configureStore](https://redux-toolkit.js.org/api/configureStore) function:
433
+
Next, open the <i>main.jsx</i> file which currently creates the Redux store. Instead of Redux's <em>createStore</em> function, let's create the store using Redux Toolkit's [configureStore](https://redux-toolkit.js.org/api/configureStore) function:
A quick way to initialize the notes state based on the data received from the server is to fetch the notes in the <i>index.js</i> file and dispatch an action using the <em>appendNote</em> action creator for each individual note object:
124
+
A quick way to initialize the notes state based on the data received from the server is to fetch the notes in the <i>main.jsx</i> file and dispatch an action using the <em>appendNote</em> action creator for each individual note object:
> **NB:** Why didn't we use await in place of promises and event handlers (registered to _then_-methods)?
217
217
>
218
-
> Await only works inside <i>async</i> functions, and the code in <i>index.js</i> is not inside a function, so due to the simple nature of the operation, we'll abstain from using <i>async</i> this time.
218
+
> Await only works inside <i>async</i> functions, and the code in <i>main.jsx</i> is not inside a function, so due to the simple nature of the operation, we'll abstain from using <i>async</i> this time.
219
219
220
220
We do, however, decide to move the initialization of the notes into the <i>App</i> component, and, as usual, when fetching data from a server, we'll use the <i>effect hook</i>.
221
221
@@ -249,48 +249,6 @@ const App = () => {
249
249
exportdefaultApp
250
250
```
251
251
252
-
Using the useEffect hook causes an eslint warning:
Now the variable <i>dispatch</i> we define in the _App_ component, which practically is the dispatch function of the redux store, has been added to the array useEffect receives as a parameter.
271
-
**If** the value of the dispatch variable would change during runtime,
272
-
the effect would be executed again. This however cannot happen in our application, so the warning is unnecessary.
273
-
274
-
Another way to get rid of the warning would be to disable ESlint on that line:
Generally disabling ESlint when it throws a warning is not a good idea. Even though the ESlint rule in question has caused some [arguments](https://github.com/facebook/create-react-app/issues/6880), we will use the first solution.
291
-
292
-
More about the need to define the hooks dependencies in [the react documentation](https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies).
293
-
294
252
### Sending data to the backend
295
253
296
254
We can do the same thing when it comes to creating a new note. Let's expand the code communicating with the server as follows:
@@ -395,7 +353,7 @@ const App = () => {
395
353
396
354
useEffect(() => {
397
355
dispatch(initializeNotes())
398
-
}, [dispatch])
356
+
}, [])
399
357
400
358
// ...
401
359
}
@@ -458,7 +416,7 @@ const App = () => {
458
416
// highlight-start
459
417
useEffect(() => {
460
418
dispatch(initializeNotes())
461
-
}, [dispatch])
419
+
}, [])
462
420
// highlight-end
463
421
464
422
return (
@@ -555,7 +513,7 @@ const NewNote = () => {
555
513
}
556
514
```
557
515
558
-
Finally, let's clean up the <i>index.js</i> file a bit by moving the code related to the creation of the Redux store into its own, <i>store.js</i> file:
516
+
Finally, let's clean up the <i>main.jsx</i> file a bit by moving the code related to the creation of the Redux store into its own, <i>store.js</i> file:
Copy file name to clipboardExpand all lines: src/content/6/fi/osa6a.md
+53-6Lines changed: 53 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -373,6 +373,53 @@ Laajennetaan reduceria siten, että se osaa käsitellä muistiinpanon tärkeytee
373
373
374
374
Koska meillä ei ole vielä koodia joka käyttää ominaisuutta, laajennetaan reduceria testivetoisesti. Aloitetaan tekemällä testi actionin <i>NEW\_NOTE</i> käsittelylle.
375
375
376
+
Konfiguroidaan sovellukseen [Jest](https://jestjs.io/). Aloitetaan asentamalla joukko kirjastoja:
377
+
378
+
```js
379
+
npm install --save-dev jest @babel/preset-env @babel/preset-react eslint-plugin-jest
380
+
```
381
+
382
+
Luodaan tiedosto <i>.babelrc</i>, jolla on seuraava sisältö:
Tiedostoon <i>.eslintrc.cjs</i> tulee myös pieni lisäys:
410
+
411
+
```js
412
+
module.exports= {
413
+
root:true,
414
+
env: {
415
+
browser:true,
416
+
es2020:true,
417
+
"jest/globals":true// highlight-line
418
+
},
419
+
// ...
420
+
}
421
+
```
422
+
376
423
Jotta testaus olisi helpompaa, siirretään reducerin koodi ensin omaan moduuliinsa tiedostoon <i>src/reducers/noteReducer.js</i>. Otetaan lisäksi käyttöön kirjasto [deep-freeze](https://www.npmjs.com/package/deep-freeze), jonka avulla voimme varmistaa, että reducer on määritelty oikeaoppisesti puhtaana funktiona. Asennetaan kirjasto kehitysaikaiseksi riippuvuudeksi:
377
424
378
425
```js
@@ -832,17 +879,17 @@ const App = () => {
832
879
833
880
Koko sovellus on toistaiseksi kirjoitettu yhteen tiedostoon minkä ansiosta joka puolelta sovellusta on päästy käsiksi Redux-storeen. Entä jos haluamme jakaa sovelluksen useisiin, omiin tiedostoihinsa sijoitettuihin komponentteihin?
834
881
835
-
Tapoja välittää Redux-store sovelluksen komponenteille on useita. Tutustutaan ensin ehkä uusimpaan ja helpoimpaan tapaan eli [react-redux](https://react-redux.js.org/)-kirjaston tarjoamaan [hooks](https://react-redux.js.org/api/hooks)-rajapintaan.
882
+
Tapoja välittää Redux-store sovelluksen komponenteille on useita. Tutustutaan ensin ehkä uusimpaan ja helpoimpaan tapaan eli [React Redux](https://react-redux.js.org/)-kirjaston tarjoamaan [hooks](https://react-redux.js.org/api/hooks)-rajapintaan.
836
883
837
884
Asennetaan react-redux:
838
885
839
886
```bash
840
887
npm install react-redux
841
888
```
842
889
843
-
Eriytetään komponentti _App_ tiedostoon _App.js_. Tarkastellaan kuitenkin ensin mitä sovelluksen muihin tiedostoihin tulee.
890
+
Eriytetään komponentti _App_ tiedostoon _App.jsx_. Tarkastellaan kuitenkin ensin mitä sovelluksen muihin tiedostoihin tulee.
844
891
845
-
Tiedosto _index.js_ näyttää seuraavalta:
892
+
Tiedosto _main.jsx_ näyttää seuraavalta:
846
893
847
894
```js
848
895
importReactfrom'react'
@@ -921,7 +968,7 @@ Normaalisti (eli ei defaultina) exportattujen funktioiden käyttöönotto tapaht
React Redux ‑kirjaston tarjoama <i>useDispatch</i>-hook siis tarjoaa mille tahansa React-komponentille pääsyn tiedostossa <i>index.js</i> määritellyn Redux-storen dispatch-funktioon, jonka avulla komponentti pääsee tekemään muutoksia Redux-storen tilaan.
1042
+
React Redux ‑kirjaston tarjoama <i>useDispatch</i>-hook siis tarjoaa mille tahansa React-komponentille pääsyn tiedostossa <i>main.jsx</i> määritellyn Redux-storen dispatch-funktioon, jonka avulla komponentti pääsee tekemään muutoksia Redux-storen tilaan.
Toisin kuin aiemmin ilman Reduxia tekemässämme React-koodissa, sovelluksen tilaa (joka on nyt siis Reduxissa) muuttava tapahtumankäsittelijä on siirretty pois <i>App</i>-komponentista, alikomponentin vastuulle. Itse tilaa muuttava logiikka on kuitenkin siististi Reduxissa eristettynä koko sovelluksen React-osuudesta.
1063
1110
1064
-
Eriytetään vielä muistiinpanojen lista ja yksittäisen muistiinpanon esittäminen omiksi komponenteikseen (jotka molemmat sijoitetaan tiedostoon <i>Notes.js</i>):
1111
+
Eriytetään vielä muistiinpanojen lista ja yksittäisen muistiinpanon esittäminen omiksi komponenteikseen (jotka molemmat sijoitetaan tiedostoon <i>Notes.jsx</i>):
0 commit comments