1 00:00:02,240 --> 00:00:06,860 Now that we learned how to restructure our reducer a little bit here, 2 00:00:07,160 --> 00:00:10,650 let's dive into more state management. 3 00:00:10,940 --> 00:00:13,670 Let's add a new state here, 4 00:00:13,800 --> 00:00:19,420 let's maybe name it results, so a new property to our state I should say and initially should be an empty 5 00:00:19,420 --> 00:00:20,280 array. 6 00:00:20,300 --> 00:00:25,100 Now let's go to our counter component here and there, 7 00:00:25,400 --> 00:00:27,570 I want to add a new button, 8 00:00:27,590 --> 00:00:34,320 so I'll first of all add a horizontal line with just hr, self-closing element and I'll add a normal button 9 00:00:34,320 --> 00:00:35,010 here 10 00:00:35,080 --> 00:00:45,710 where I'll simply say STORE_RESULT, like this and this result should get added to an unordered list, 11 00:00:45,710 --> 00:00:50,490 this all has no styling right now which I create below that button. 12 00:00:50,510 --> 00:01:01,070 Now the idea is that when I click STORE_RESULT, that I simply add the current counter value to my result 13 00:01:01,070 --> 00:01:02,120 list here, 14 00:01:02,540 --> 00:01:09,290 so for that of course I want to dispatch an action whenever this button is clicked and then push this 15 00:01:09,290 --> 00:01:11,310 new result to this results 16 00:01:11,330 --> 00:01:13,730 array, update that array with it 17 00:01:14,210 --> 00:01:17,130 and of course, take the current counter as input. 18 00:01:17,510 --> 00:01:23,900 Additionally if I click one of these results, so one of these list items, I want to remove it from the 19 00:01:23,900 --> 00:01:24,520 array, 20 00:01:24,830 --> 00:01:28,580 so it should have an ID, something like that by which I can identify it 21 00:01:28,910 --> 00:01:37,480 and I want to remove that list item thereafter. For this, I first of all will start here in my container 22 00:01:37,490 --> 00:01:38,190 component 23 00:01:38,390 --> 00:01:44,240 even though I haven't worked on the reducer or anything like that and I'll simply add two new props 24 00:01:44,240 --> 00:01:51,560 to mapDispatchToProps because I need two new functions basically, two new dispatch functions. 25 00:01:51,560 --> 00:01:54,570 One could be on STORE_RESULT, 26 00:01:54,890 --> 00:02:00,920 this should hold an anonymous function where I dispatch, I dispatch a javascript object which needs to 27 00:02:00,920 --> 00:02:02,020 have a type, 28 00:02:02,090 --> 00:02:08,680 this could be STORE_RESULT and the value should be a current counter value of course. 29 00:02:08,690 --> 00:02:14,750 Now this is something I don't need to pass as a payload though because since the counter is part of 30 00:02:14,750 --> 00:02:20,360 my application state, I will have access to it in my reducer anyways later, 31 00:02:20,360 --> 00:02:22,680 so I don't need to pass it here as payload. 32 00:02:22,730 --> 00:02:28,130 Of course you could also have use cases where you want to store some result the user entered, then you wouldn't 33 00:02:28,130 --> 00:02:31,430 pass it as a value from your component, here 34 00:02:31,430 --> 00:02:35,050 however, it's not required. I'll then duplicate this 35 00:02:35,240 --> 00:02:42,170 and I'll also set our property which I'll name onDeleteResult, where I want to dispatch an actual 36 00:02:42,180 --> 00:02:45,580 let's say with the identifier, delete result. 37 00:02:45,590 --> 00:02:50,720 Now I have these two props and I'll connect them in my container, here 38 00:02:50,990 --> 00:02:58,250 I'll add the onClick listener to the STORE_RESULT button and I'll execute this.props.onStoreResult, 39 00:02:58,820 --> 00:03:05,570 no parentheses as always, this is just a reference to a method and it will get executed automatically. 40 00:03:05,960 --> 00:03:12,130 And on the list item here, I'll also add a click listener where I'll say onDelete, 41 00:03:12,140 --> 00:03:17,000 so this.props.onDeleteResult. 42 00:03:17,030 --> 00:03:22,970 Now of course, this list doesn't have any content yet, we'll later dynamically create a list of items here, 43 00:03:23,060 --> 00:03:30,790 so for now, let's focus on this button here with the STORE_RESULT prop, when we click this button, 44 00:03:31,060 --> 00:03:34,990 right now, I have the console open, nothing happens. 45 00:03:34,990 --> 00:03:38,310 We also don't get an error, notice this, 46 00:03:38,710 --> 00:03:44,190 so you can dispatch actions which you actually don't handle in the reducer, 47 00:03:44,210 --> 00:03:52,150 that's the first important takeaway. We are dispatching STORE_RESULT here because we're binding on store 48 00:03:52,150 --> 00:03:54,600 result which executes this method, 49 00:03:54,910 --> 00:03:56,780 we're binding that to the button, 50 00:03:56,830 --> 00:04:04,060 so this action does get dispatched and it does reach the reducer because we only have one single reducer 51 00:04:04,060 --> 00:04:09,370 in our react app and therefore all actions make it through that reducer. 52 00:04:09,430 --> 00:04:18,850 But since I simply ignore it here, I have no case handling action with the type STORE_RESULT, I get to this 53 00:04:18,850 --> 00:04:22,600 line here where I return the current state, 54 00:04:22,660 --> 00:04:23,490 that's it. 55 00:04:23,500 --> 00:04:28,330 I just returned the current state which also means that if I changed the counter through my buttons up here 56 00:04:28,690 --> 00:04:31,960 and I click this, I don't reset the state, 57 00:04:31,960 --> 00:04:33,800 I don't return the initial state, 58 00:04:33,880 --> 00:04:36,160 I return the current state, 59 00:04:36,160 --> 00:04:38,120 so that's the first important takeaway. 60 00:04:38,500 --> 00:04:40,290 But let's now handle this, 61 00:04:40,450 --> 00:04:48,700 let's create a new case where I say STORE_RESULT and there, I want to return, 62 00:04:48,700 --> 00:04:55,890 now I want to return what? I want to return an updated version of my state 63 00:04:56,080 --> 00:05:04,810 and we should this immutable, right now in all the cases, we'll always return a new javascript object where 64 00:05:04,810 --> 00:05:11,920 we only update the counter for the single reason that we only have the counter property there, 65 00:05:11,950 --> 00:05:17,950 the whole state previously was made up only by the counter property. 66 00:05:17,950 --> 00:05:24,220 Now we also have a results property which is an array and therefore right now, if we increment, decrement 67 00:05:24,280 --> 00:05:31,480 add or subtract, we basically remove that from our state because we return the updated version of the 68 00:05:31,480 --> 00:05:38,190 state and it just is a javascript object with the updated counter but without a results property. 69 00:05:38,630 --> 00:05:42,440 And unlike set state did in react, 70 00:05:42,550 --> 00:05:46,670 this is not merged with the old state or anything like that, 71 00:05:46,690 --> 00:05:49,480 this is the new state instead. 72 00:05:49,810 --> 00:05:52,880 So here, the new state doesn't have results anymore 73 00:05:53,110 --> 00:05:57,060 so actually this is not how we should update the state, 74 00:05:57,100 --> 00:06:04,070 instead we should copy the old state properties and then only update the ones which need updating and this should 75 00:06:04,120 --> 00:06:04,580 happen 76 00:06:04,600 --> 00:06:14,500 immutably. So what we don't do is we don't set const newState equal to state and then set newState.Counter 77 00:06:14,500 --> 00:06:22,530 equals state.counter plus 1 and then we return newState here, 78 00:06:22,540 --> 00:06:24,620 this is not how we do it. 79 00:06:24,700 --> 00:06:26,330 Why do we not do it like this? 80 00:06:26,470 --> 00:06:29,260 Because we're mutating the old state here, 81 00:06:29,740 --> 00:06:33,300 instead what we do is we copy the old state. 82 00:06:33,400 --> 00:06:41,140 Now one way of doing this is calling object.assign, passing an empty javascript object us to the first 83 00:06:41,140 --> 00:06:47,420 argument and the old javascript object we want to copy as the second state here, 84 00:06:48,520 --> 00:06:49,900 like that. 85 00:06:49,990 --> 00:06:55,240 Now this will basically clone the old object in an immutable way 86 00:06:55,660 --> 00:07:02,950 giving us a new javascript object which has all the properties of the old object but is a technically 87 00:07:02,950 --> 00:07:09,700 different object and that of course is important due to the way objects and array work in javascript 88 00:07:09,970 --> 00:07:14,980 with the reference types or these primitive types, if that is unclear, 89 00:07:14,980 --> 00:07:16,210 definitely check this out, 90 00:07:16,210 --> 00:07:19,290 it is a core concept of javascript. 91 00:07:19,330 --> 00:07:24,150 Now with that we get a copy, though important, not a deep clone, 92 00:07:24,190 --> 00:07:32,170 so our results array still is the same object as it is here in the initial state. But here it doesn't matter, 93 00:07:32,170 --> 00:07:35,130 we get a copy of our state, the new state, 94 00:07:35,170 --> 00:07:41,140 now there if we change the counter, we're not doing this in the old state but in that copied state and 95 00:07:41,140 --> 00:07:43,960 we're returning that updated copied state. 96 00:07:44,170 --> 00:07:51,070 This will then become the new state and it is a technically new object and that's important. 97 00:07:51,160 --> 00:07:52,980 Now you can write it like this, 98 00:07:53,110 --> 00:07:59,890 the shorter way is to simply return a javascript object and there, distribute all the properties of the 99 00:07:59,890 --> 00:08:06,500 old state which you can do with the spread operator, state like this ...state. 100 00:08:07,390 --> 00:08:12,430 This simply tells javascript return a javascript object, 101 00:08:12,730 --> 00:08:18,860 take all the properties and values of the state argument which is our old state, 102 00:08:18,970 --> 00:08:27,160 distribute these properties with their values in this new object and then since we define an additional 103 00:08:27,160 --> 00:08:35,410 property, add this property to the object or if it already was present due to us distributing the old 104 00:08:35,410 --> 00:08:39,120 state as it would be for the counter, this is part of the old state, 105 00:08:39,430 --> 00:08:43,630 overwrite this but only this, leave results untouched. 106 00:08:43,630 --> 00:08:49,690 This is what's happening here, we're distributing the old state, we're overwriting counter, we're not touching 107 00:08:49,690 --> 00:08:50,900 results. 108 00:08:51,130 --> 00:08:54,830 So this is how we should update the state in all cases, 109 00:08:54,970 --> 00:09:03,490 do it immutably, don't touch the old state, don't just return a new object without covering all the properties 110 00:09:03,490 --> 00:09:04,540 of the old state 111 00:09:04,660 --> 00:09:09,530 or you're about to delete properties from your state, as we previously did. 112 00:09:10,000 --> 00:09:17,020 And with that in STORE_RESULT, we also return a javascript object where we distribute the old state thus 113 00:09:17,020 --> 00:09:18,420 keeping the counter 114 00:09:18,850 --> 00:09:21,250 but then we set results here. 115 00:09:21,280 --> 00:09:24,200 So this results property we want to update, 116 00:09:24,520 --> 00:09:32,650 we can set an equal to state results and then we can call concat which simply is like push but where 117 00:09:32,660 --> 00:09:35,650 push manipulates the original value, 118 00:09:35,670 --> 00:09:43,520 concat returns a new array which is the older array plus the argument you add to concat. 119 00:09:43,660 --> 00:09:47,510 So it's an immutable way of updating an array by adding an item, 120 00:09:47,620 --> 00:09:51,140 it returns a new array, that's the key thing here 121 00:09:51,280 --> 00:09:54,230 because arrays also are reference types, 122 00:09:54,310 --> 00:09:55,920 if you would call push, 123 00:09:56,040 --> 00:10:01,660 you are touching the original results property in the original state, even though you used the spread 124 00:10:01,660 --> 00:10:02,670 operator here, 125 00:10:02,680 --> 00:10:04,670 that doesn't prevent you from doing that 126 00:10:04,840 --> 00:10:06,700 and this is not a good practice, 127 00:10:06,730 --> 00:10:07,970 not how you should do it, 128 00:10:07,990 --> 00:10:11,440 your state management becomes unpredictable if you do it. 129 00:10:11,440 --> 00:10:16,090 So use concat and now push whatever you want to add to this array, 130 00:10:16,090 --> 00:10:23,020 for example here we could add state counter since we want to store a snapshot of the counter and push 131 00:10:23,020 --> 00:10:24,440 it to the results array. 132 00:10:25,630 --> 00:10:31,180 Now with that, we updated our state immutably for all cases, 133 00:10:31,480 --> 00:10:34,380 you learned how to update an array in your state 134 00:10:34,390 --> 00:10:37,580 immutably with concat by adding a new item 135 00:10:38,290 --> 00:10:43,970 and now, we can return that state here where we do return it here actually and we can use it in our 136 00:10:43,970 --> 00:10:52,600 counter component. There we can now bind it in mapStateToProps to a new prop, maybe a stored results 137 00:10:52,630 --> 00:10:59,800 prop which should be state.results, referring to that property name you set up in the reducer, results, 138 00:10:59,800 --> 00:11:00,960 this has to be equal 139 00:11:00,970 --> 00:11:07,580 so we're retrieving this state property and now, we can use stored results which we can access through 140 00:11:07,610 --> 00:11:11,880 this props here in our render method. 141 00:11:12,230 --> 00:11:17,830 So here for the list item where I want to output them, I'll do it inline here with curly braces, 142 00:11:18,020 --> 00:11:27,680 I can say this.props.storedResults.map and now map each stored result which I'll store in this argument 143 00:11:27,690 --> 00:11:31,890 here, I'll map it to this list item. 144 00:11:31,950 --> 00:11:39,150 So I'll simply wrap my list item and put it into my map method here to as always map this array of 145 00:11:39,150 --> 00:11:44,100 stored results into an array of jsx list items and there, 146 00:11:44,100 --> 00:11:51,860 now we have our new list item where we of course can output stored result. 147 00:11:52,140 --> 00:11:54,440 And now this would be our result 148 00:11:54,690 --> 00:11:58,890 but actually, I want to go back to the reducer and change it a tiny bit, 149 00:11:58,890 --> 00:12:01,000 I don't just want to store a number, 150 00:12:01,290 --> 00:12:07,140 I want to create an object and this is kind of optional here but I want to do it because I don't just 151 00:12:07,140 --> 00:12:09,350 want to have my result value 152 00:12:09,510 --> 00:12:12,970 and you could name this val, v, whatever you want, 153 00:12:12,990 --> 00:12:18,090 I also want to create an id here and that id should be something unique, 154 00:12:18,390 --> 00:12:24,540 so I'll simply use new date which is simply a snapshot of the date when this was added. 155 00:12:24,540 --> 00:12:28,650 Now I have an id and a value and now back in the counter component, 156 00:12:28,680 --> 00:12:37,130 I can use both storedResult_value referring to that value property here in the object 157 00:12:37,130 --> 00:12:41,690 I pushed to that array or I concat to this array to be precise 158 00:12:41,910 --> 00:12:50,480 and since we have a list, we need to set a key that can set this key to storedResult.id, that date snapshot. 159 00:12:50,910 --> 00:12:57,330 Now with that, if we go back to the application and I click Add 10 and I click store result, we see 10 here 160 00:12:57,360 --> 00:12:58,300 added in the middle, 161 00:12:58,320 --> 00:12:59,580 let me add 10 again, 162 00:12:59,580 --> 00:13:02,010 now we store 20 as a second value, 163 00:13:02,010 --> 00:13:03,000 So now we are storing 164 00:13:03,030 --> 00:13:07,140 all these values. Clicking on them doesn't do much, 165 00:13:07,140 --> 00:13:10,980 it also doesn't throw an error but of course we're not handling this 166 00:13:10,980 --> 00:13:16,150 click listener where I want to delete the result and therefore dispatch delete result. 167 00:13:16,290 --> 00:13:18,810 So let's implement this in the next lecture.