1 00:00:00,000 --> 00:00:02,450 [MUSIC PLAYING] 2 00:00:02,450 --> 00:00:16,412 3 00:00:16,412 --> 00:00:18,620 JORDAN HAYASHI: Hello and welcome back for lecture 9. 4 00:00:18,620 --> 00:00:20,604 This week we'll be talking about Redux. 5 00:00:20,604 --> 00:00:23,270 So in the last couple of lectures, we talked about a few things. 6 00:00:23,270 --> 00:00:26,180 We talked about APIs, which is the way that you interface 7 00:00:26,180 --> 00:00:28,160 with external-facing services. 8 00:00:28,160 --> 00:00:30,170 We talked about making network requests, so how 9 00:00:30,170 --> 00:00:33,530 do you actually access these APIs if they're not on your own computer-- 10 00:00:33,530 --> 00:00:35,616 maybe out in the cloud somewhere. 11 00:00:35,616 --> 00:00:37,490 And we talked about promises and async/await, 12 00:00:37,490 --> 00:00:41,570 which are basically a couple ways to handle asynchronous actions, namely 13 00:00:41,570 --> 00:00:43,090 making network requests. 14 00:00:43,090 --> 00:00:46,430 We talked about how to transform data after you get it back from an API. 15 00:00:46,430 --> 00:00:48,710 It might not be exactly in the shape that you want. 16 00:00:48,710 --> 00:00:50,751 And so we talked about a few different strategies 17 00:00:50,751 --> 00:00:52,880 by which we could get it from the shape that it's 18 00:00:52,880 --> 00:00:56,390 in from the API to exactly what we want in our application. 19 00:00:56,390 --> 00:00:58,470 We then talked about some simple authentication, 20 00:00:58,470 --> 00:01:01,770 meaning how do you ensure that users are who they say they are? 21 00:01:01,770 --> 00:01:04,760 And how do you let them into your app after that? 22 00:01:04,760 --> 00:01:07,430 We talked about some HTTP methods and response codes, 23 00:01:07,430 --> 00:01:14,720 which are basically a specification that lets you take a response from a network 24 00:01:14,720 --> 00:01:18,530 request and know exactly if the request succeeded or if it failed. 25 00:01:18,530 --> 00:01:20,720 And if it failed, then why did it fail? 26 00:01:20,720 --> 00:01:23,930 And then lastly, last week, we had Charlie Cheever as our guest 27 00:01:23,930 --> 00:01:25,746 to talk about expo components. 28 00:01:25,746 --> 00:01:29,010 29 00:01:29,010 --> 00:01:31,310 So our applications, as we move throughout the class, 30 00:01:31,310 --> 00:01:32,960 are getting more and more complex. 31 00:01:32,960 --> 00:01:35,460 And now we're starting to run into some problems. 32 00:01:35,460 --> 00:01:37,910 Our apps thus far have been pretty simple. 33 00:01:37,910 --> 00:01:42,170 But we're already starting to see some bugs related to complexity, namely 34 00:01:42,170 --> 00:01:47,570 maybe we forget to pass a prop or have some troubles directly 35 00:01:47,570 --> 00:01:51,529 managing some state that's possibly deeply nested. 36 00:01:51,529 --> 00:01:53,570 With more complicated state, we might be starting 37 00:01:53,570 --> 00:01:57,230 to duplicate some information in that state object. 38 00:01:57,230 --> 00:02:00,050 Or maybe with that duplicated information, 39 00:02:00,050 --> 00:02:01,910 when we update one of the props, maybe we 40 00:02:01,910 --> 00:02:06,410 forget to update another prop or a bunch of the other dependent props. 41 00:02:06,410 --> 00:02:08,660 Or maybe we have components with the very large number 42 00:02:08,660 --> 00:02:13,430 of props that don't necessarily need to have that large number of props. 43 00:02:13,430 --> 00:02:15,620 Or maybe we see a prop that's not behaving 44 00:02:15,620 --> 00:02:18,200 how we think it should be behaving, and we're not really sure 45 00:02:18,200 --> 00:02:21,920 where exactly it's going wrong and where that props should be being managed. 46 00:02:21,920 --> 00:02:25,610 And so this lecture, we're going to take a step back and rethink 47 00:02:25,610 --> 00:02:29,670 the architecture by which we've been managing our data. 48 00:02:29,670 --> 00:02:33,800 So one company that's run into scaling issues is Facebook. 49 00:02:33,800 --> 00:02:37,220 So they found that the MVC architecture is a little bit 50 00:02:37,220 --> 00:02:39,050 too complex for their scale. 51 00:02:39,050 --> 00:02:43,550 And so those of you who took CS50, we talked about this architecture called 52 00:02:43,550 --> 00:02:44,840 model view controller. 53 00:02:44,840 --> 00:02:47,270 And what exactly is that? 54 00:02:47,270 --> 00:02:51,710 So in the MVC architecture, we have models. 55 00:02:51,710 --> 00:02:54,650 56 00:02:54,650 --> 00:02:55,535 We have views. 57 00:02:55,535 --> 00:02:59,670 58 00:02:59,670 --> 00:03:01,245 And we have controllers. 59 00:03:01,245 --> 00:03:06,580 60 00:03:06,580 --> 00:03:09,790 And so views are basically what a user sees. 61 00:03:09,790 --> 00:03:11,710 And the data by which-- 62 00:03:11,710 --> 00:03:15,790 are loaded into the views come from these models. 63 00:03:15,790 --> 00:03:17,772 And how does a user interface with these views? 64 00:03:17,772 --> 00:03:20,105 Well, they do it through this thing called a controller. 65 00:03:20,105 --> 00:03:22,840 66 00:03:22,840 --> 00:03:26,862 And then maybe the controller will then dispatch an action 67 00:03:26,862 --> 00:03:28,570 when a user clicks a button or something. 68 00:03:28,570 --> 00:03:32,880 And maybe that goes and updates a model. 69 00:03:32,880 --> 00:03:37,480 But also some views might directly change models. 70 00:03:37,480 --> 00:03:40,990 And so you start to have this two-way connection between models and views. 71 00:03:40,990 --> 00:03:43,540 And when you're operating at Facebook size, 72 00:03:43,540 --> 00:03:45,850 you don't just have one model and one view. 73 00:03:45,850 --> 00:03:48,310 Facebook actually has something like 30,000 different React 74 00:03:48,310 --> 00:03:49,694 components that they use. 75 00:03:49,694 --> 00:03:51,610 And so there are a large number of views here. 76 00:03:51,610 --> 00:03:56,975 77 00:03:56,975 --> 00:03:58,850 And with that larger number of views, they're 78 00:03:58,850 --> 00:04:00,815 also a very large number of models. 79 00:04:00,815 --> 00:04:05,720 80 00:04:05,720 --> 00:04:10,820 And maybe this view talks to this model, and back and forth, and also 81 00:04:10,820 --> 00:04:12,320 talks to that model. 82 00:04:12,320 --> 00:04:15,050 And maybe that view talks to this model. 83 00:04:15,050 --> 00:04:16,940 And now with all of these connections, you 84 00:04:16,940 --> 00:04:19,106 see how it's starting to get very, very complicated. 85 00:04:19,106 --> 00:04:21,260 And when you scale up to a size like Facebook, 86 00:04:21,260 --> 00:04:23,510 you might start to run into some bugs. 87 00:04:23,510 --> 00:04:27,200 And so one thing that happened with Facebook 88 00:04:27,200 --> 00:04:30,830 is that the complexity manifested itself into some bugs, and namely 89 00:04:30,830 --> 00:04:35,030 a pretty famous one that has to do with unread chat notifications. 90 00:04:35,030 --> 00:04:37,850 And so what basically happened was Facebook 91 00:04:37,850 --> 00:04:42,160 started to add more and more different views for how you access their chat. 92 00:04:42,160 --> 00:04:46,140 And so at first it was a little pop-up box that happened in the bottom. 93 00:04:46,140 --> 00:04:48,890 But then they added a separate page for chats, 94 00:04:48,890 --> 00:04:52,130 and then they added something in the nav bar that drops down with some chats. 95 00:04:52,130 --> 00:04:54,830 And then they started adding other applications that handle chats. 96 00:04:54,830 --> 00:04:57,080 And all of a sudden, there's a lot of different places 97 00:04:57,080 --> 00:05:01,200 where a chat could be updated or vise versa. 98 00:05:01,200 --> 00:05:05,210 And so they had a big bug where users would log in, 99 00:05:05,210 --> 00:05:08,607 and it would have a notification that says you have an unread message. 100 00:05:08,607 --> 00:05:10,440 But that wasn't necessarily always the case. 101 00:05:10,440 --> 00:05:12,530 And so this bugged a lot of users, and Facebook 102 00:05:12,530 --> 00:05:15,920 had to take a step back and figure out a better way 103 00:05:15,920 --> 00:05:18,170 to handle this large complexity that they're 104 00:05:18,170 --> 00:05:20,540 starting to have in their application. 105 00:05:20,540 --> 00:05:22,790 And so what they did is they re-architected everything 106 00:05:22,790 --> 00:05:25,040 into a single-direction data flow. 107 00:05:25,040 --> 00:05:28,250 And so data only comes in from one direction, 108 00:05:28,250 --> 00:05:31,190 and there's only one way to update that data. 109 00:05:31,190 --> 00:05:32,820 And how did they do that? 110 00:05:32,820 --> 00:05:34,940 Well, they created-- well, if you want to see 111 00:05:34,940 --> 00:05:37,310 additional background into this problem, you 112 00:05:37,310 --> 00:05:39,570 can watch this YouTube video by Jing Chen. 113 00:05:39,570 --> 00:05:42,110 And they talk about exactly what the bug was 114 00:05:42,110 --> 00:05:44,900 and why they created this new architecture. 115 00:05:44,900 --> 00:05:47,720 And so this new architecture was called Flux. 116 00:05:47,720 --> 00:05:49,130 And what is Flux. 117 00:05:49,130 --> 00:05:51,740 Well, it's a new application architecture for React 118 00:05:51,740 --> 00:05:54,920 that utilizes a unidirectional data flow. 119 00:05:54,920 --> 00:05:56,520 What the heck does that mean? 120 00:05:56,520 --> 00:06:02,150 Well, views react in changes to some number of stores. 121 00:06:02,150 --> 00:06:04,460 And what it stores, it stores the data. 122 00:06:04,460 --> 00:06:08,270 And the only thing that can update this data is this thing called a dispatcher, 123 00:06:08,270 --> 00:06:12,130 and we'll talk about it a little more in a sec. 124 00:06:12,130 --> 00:06:14,060 And how do we trigger this dispatcher? 125 00:06:14,060 --> 00:06:16,312 Well, you invoke an action. 126 00:06:16,312 --> 00:06:18,020 And what is the way you invoke an action? 127 00:06:18,020 --> 00:06:21,010 Well, actions are triggered from views. 128 00:06:21,010 --> 00:06:22,540 And so let's draw this picture out. 129 00:06:22,540 --> 00:06:32,320 130 00:06:32,320 --> 00:06:36,699 So you have a central store that stores all of your information, 131 00:06:36,699 --> 00:06:37,990 or maybe some number of stores. 132 00:06:37,990 --> 00:06:46,980 133 00:06:46,980 --> 00:06:50,630 And these stores will store all of the data 134 00:06:50,630 --> 00:06:52,705 that you need for that application. 135 00:06:52,705 --> 00:06:54,080 And how do you update that store? 136 00:06:54,080 --> 00:06:56,163 Well, it's through this thing called a dispatcher. 137 00:06:56,163 --> 00:07:02,830 138 00:07:02,830 --> 00:07:08,630 And so this dispatcher will actually send information to these stores. 139 00:07:08,630 --> 00:07:09,850 And these stores will update. 140 00:07:09,850 --> 00:07:13,330 And that's the only possible way to update these stores. 141 00:07:13,330 --> 00:07:15,962 And how do you trigger the dispatcher? 142 00:07:15,962 --> 00:07:17,920 Well, it's through this thing called an action. 143 00:07:17,920 --> 00:07:23,861 144 00:07:23,861 --> 00:07:26,610 And what happens when you have all this information in your store. 145 00:07:26,610 --> 00:07:29,580 You use that store to render a bunch of views. 146 00:07:29,580 --> 00:07:36,420 And so maybe this view listens from this store and that store. 147 00:07:36,420 --> 00:07:43,200 And maybe a view here listens to all three stores. 148 00:07:43,200 --> 00:07:48,270 And the view here only listens to that store. 149 00:07:48,270 --> 00:07:52,260 And so we have a large number of arrows here, potentially. 150 00:07:52,260 --> 00:07:54,870 But one thing to note is that the arrows all 151 00:07:54,870 --> 00:08:01,050 go this direction, which means that there is no bi-directional flow. 152 00:08:01,050 --> 00:08:04,440 And so multiple views don't necessarily update, 153 00:08:04,440 --> 00:08:07,330 or they can't update, multiple stores. 154 00:08:07,330 --> 00:08:09,880 Which is a good thing because a view can just say, 155 00:08:09,880 --> 00:08:12,290 hey, give me the information from here and here. 156 00:08:12,290 --> 00:08:16,140 But I'm not going to worry about having to go update those back. 157 00:08:16,140 --> 00:08:18,480 What I do is I dispatch an action. 158 00:08:18,480 --> 00:08:26,030 And so these views are the ways to trigger an action, 159 00:08:26,030 --> 00:08:28,640 and the only ways to trigger an action. 160 00:08:28,640 --> 00:08:32,960 And so you see what is looking like a large number of arrows, 161 00:08:32,960 --> 00:08:35,460 but you see that they're all going in a singular direction. 162 00:08:35,460 --> 00:08:38,390 So you have this unidirectional data flow. 163 00:08:38,390 --> 00:08:42,110 So to repeat myself, the only way to update 164 00:08:42,110 --> 00:08:44,740 the information, the data that's stored in an application, 165 00:08:44,740 --> 00:08:46,490 is through this thing called a dispatcher. 166 00:08:46,490 --> 00:08:48,770 And we don't really control this dispatcher. 167 00:08:48,770 --> 00:08:54,110 We only tell the dispatcher to start by dispatching an action. 168 00:08:54,110 --> 00:08:55,820 And how do we trigger an action? 169 00:08:55,820 --> 00:08:58,820 Well, we interact with the views. 170 00:08:58,820 --> 00:09:01,820 And by we, I mean our users. 171 00:09:01,820 --> 00:09:04,220 And how do these views know what they should render? 172 00:09:04,220 --> 00:09:06,470 Well, they get that information from stores. 173 00:09:06,470 --> 00:09:09,440 And as stores are updated, the views are automatically 174 00:09:09,440 --> 00:09:11,730 notified that they should re-render. 175 00:09:11,730 --> 00:09:14,360 And so there's no arrows that are going back and forth here, 176 00:09:14,360 --> 00:09:16,670 so the complexity is an order of magnitude 177 00:09:16,670 --> 00:09:19,419 smaller, because the views only care about the information 178 00:09:19,419 --> 00:09:20,960 that they're getting from the stores. 179 00:09:20,960 --> 00:09:23,668 And they're automatically notified when that information changes. 180 00:09:23,668 --> 00:09:30,640 181 00:09:30,640 --> 00:09:32,990 So Flux is a general architecture. 182 00:09:32,990 --> 00:09:37,000 And there are actually many implementations. 183 00:09:37,000 --> 00:09:40,060 Facebook has written one. 184 00:09:40,060 --> 00:09:42,580 There's also this thing called Redux. 185 00:09:42,580 --> 00:09:46,360 So whether or not Redux is actually an implementation of Flux 186 00:09:46,360 --> 00:09:48,920 is an opinion that can be argued either way. 187 00:09:48,920 --> 00:09:53,340 But what's unarguable is that Redux was inspired by Flux. 188 00:09:53,340 --> 00:09:57,790 So Redux is a data management library, and it takes a lot of the paradigms 189 00:09:57,790 --> 00:10:02,050 that Flux created and implements them for itself. 190 00:10:02,050 --> 00:10:05,230 And so there are three big pillars of Redux. 191 00:10:05,230 --> 00:10:08,300 One is that there is a single source of truth for all of the data. 192 00:10:08,300 --> 00:10:11,130 So in the Flux architecture, there might be multiple stores. 193 00:10:11,130 --> 00:10:13,810 But in Redux, there's just one, one big object 194 00:10:13,810 --> 00:10:18,040 that keeps track of all the application state. 195 00:10:18,040 --> 00:10:20,260 The only way that you can update the state 196 00:10:20,260 --> 00:10:23,400 is by an action that triggers a re-computation of the state. 197 00:10:23,400 --> 00:10:27,610 And so it's very similar to the Flux in that the only way that you can update 198 00:10:27,610 --> 00:10:30,580 a store is by dispatching an action. 199 00:10:30,580 --> 00:10:33,250 And Redux is very similar in that the only way 200 00:10:33,250 --> 00:10:37,090 to update the centralized data-- 201 00:10:37,090 --> 00:10:45,820 so you can think of the store as one big thing in Redux. 202 00:10:45,820 --> 00:10:48,990 And the only way to update that is by dispatching an action. 203 00:10:48,990 --> 00:10:54,640 204 00:10:54,640 --> 00:10:58,360 And lastly, updates are made using a pure function. 205 00:10:58,360 --> 00:11:02,320 And so by pure function, I mean a function that takes in arguments 206 00:11:02,320 --> 00:11:05,090 and will always return the same thing for those arguments. 207 00:11:05,090 --> 00:11:08,740 So it's fully deterministic, meaning given the same arguments, 208 00:11:08,740 --> 00:11:10,766 it will always return the same answer. 209 00:11:10,766 --> 00:11:12,640 And also, it doesn't look anywhere else other 210 00:11:12,640 --> 00:11:15,880 than those arguments for the computation that it gives. 211 00:11:15,880 --> 00:11:19,360 So you're not using things like the current time 212 00:11:19,360 --> 00:11:21,970 or anything in the environment to calculate things, 213 00:11:21,970 --> 00:11:24,957 only a function of the input. 214 00:11:24,957 --> 00:11:26,540 And lastly, there are no side effects. 215 00:11:26,540 --> 00:11:30,362 So I take input, and I give output. 216 00:11:30,362 --> 00:11:31,570 And I don't do anything else. 217 00:11:31,570 --> 00:11:32,510 I don't print. 218 00:11:32,510 --> 00:11:35,051 I don't change variables outside my scope, nothing like that. 219 00:11:35,051 --> 00:11:37,250 220 00:11:37,250 --> 00:11:38,470 And so we have this thing. 221 00:11:38,470 --> 00:11:43,010 We have an action, goes to a reducer, which then updates the store. 222 00:11:43,010 --> 00:11:45,520 And so to draw that-- 223 00:11:45,520 --> 00:11:48,850 if you remember this from Flux, we have actions 224 00:11:48,850 --> 00:11:53,050 go through a dispatcher, which updates some number of stores, 225 00:11:53,050 --> 00:11:55,780 which then update some number of views. 226 00:11:55,780 --> 00:12:09,380 And in Reduxland, we have an action, gets dispatched, 227 00:12:09,380 --> 00:12:11,210 and updates some central store. 228 00:12:11,210 --> 00:12:15,520 229 00:12:15,520 --> 00:12:19,180 And that will update any of its views. 230 00:12:19,180 --> 00:12:32,140 231 00:12:32,140 --> 00:12:37,090 And those views, with user interaction, can trigger more actions. 232 00:12:37,090 --> 00:12:39,190 And so it's a very similar diagram to Flux. 233 00:12:39,190 --> 00:12:43,780 And it's the exact same in that it's a unidirectional flow of data. 234 00:12:43,780 --> 00:12:46,150 But the main difference is here where you 235 00:12:46,150 --> 00:12:50,710 have a singular store, rather than a potentially large number of stores 236 00:12:50,710 --> 00:12:51,350 like in Flux. 237 00:12:51,350 --> 00:12:58,130 238 00:12:58,130 --> 00:13:01,100 And if you want to read about Redux and its background, 239 00:13:01,100 --> 00:13:02,960 you can go to this URL, which is ITS Docs. 240 00:13:02,960 --> 00:13:06,780 241 00:13:06,780 --> 00:13:09,890 So let's do something fun this lecture and actually implement 242 00:13:09,890 --> 00:13:12,490 something like Redux ourselves. 243 00:13:12,490 --> 00:13:13,620 And so where do we start? 244 00:13:13,620 --> 00:13:21,457 Let's go ahead and just create a directory 245 00:13:21,457 --> 00:13:23,290 into which we'll start creating these files. 246 00:13:23,290 --> 00:13:27,890 247 00:13:27,890 --> 00:13:29,540 So what's first? 248 00:13:29,540 --> 00:13:32,840 So there's this thing called a reducer, which 249 00:13:32,840 --> 00:13:35,430 is what calculates the next state. 250 00:13:35,430 --> 00:13:38,870 And so it takes a previous state, and it takes some information 251 00:13:38,870 --> 00:13:40,330 on how it should update. 252 00:13:40,330 --> 00:13:43,680 And it goes ahead and applies the update and returns some new state. 253 00:13:43,680 --> 00:13:47,640 So some constraints, it should be a pure function. 254 00:13:47,640 --> 00:13:49,630 So in other words, the result is deterministic. 255 00:13:49,630 --> 00:13:52,510 So given the same input, it'll always give the same output. 256 00:13:52,510 --> 00:13:56,120 And it's determined exclusively by those arguments. 257 00:13:56,120 --> 00:13:59,000 And there are no side effects, so no logging, no changing variables, 258 00:13:59,000 --> 00:14:00,680 no doing anything like that-- 259 00:14:00,680 --> 00:14:03,740 no changing variables outside of its own scope that should. 260 00:14:03,740 --> 00:14:05,010 Should be immutable. 261 00:14:05,010 --> 00:14:08,160 And so we've talked about immutability in previous lectures. 262 00:14:08,160 --> 00:14:11,790 So it should always return a new object. 263 00:14:11,790 --> 00:14:14,014 So the keys in the object might not change, 264 00:14:14,014 --> 00:14:15,930 but the object reference itself should change. 265 00:14:15,930 --> 00:14:18,979 266 00:14:18,979 --> 00:14:21,520 And let's actually go ahead and start implementing a reducer. 267 00:14:21,520 --> 00:14:25,820 268 00:14:25,820 --> 00:14:31,340 And so we said a reducer takes the previous state and some sort of update 269 00:14:31,340 --> 00:14:32,930 and returns some new state. 270 00:14:32,930 --> 00:14:34,700 And let's go ahead and implement that. 271 00:14:34,700 --> 00:14:40,010 272 00:14:40,010 --> 00:14:47,200 So some function that takes a previous state and an update 273 00:14:47,200 --> 00:14:48,940 and it returns some sort of new state. 274 00:14:48,940 --> 00:14:52,630 And so how it calculates that state is completely up to us. 275 00:14:52,630 --> 00:14:55,690 And so let's make the simplest reducer possible. 276 00:14:55,690 --> 00:14:59,410 Well, the simplest reducer possible would actually be this, 277 00:14:59,410 --> 00:15:03,330 where we take the previous date, we take an update, 278 00:15:03,330 --> 00:15:06,800 and we just completely ignore the update and return the previous state. 279 00:15:06,800 --> 00:15:08,810 But let's actually do something. 280 00:15:08,810 --> 00:15:12,160 So rather than just returning the state blindly, let's apply some update. 281 00:15:12,160 --> 00:15:15,960 And so let's assume the state isn't an object, 282 00:15:15,960 --> 00:15:18,710 and let's assume the update is also an object. 283 00:15:18,710 --> 00:15:21,885 And let's just merge those objects. 284 00:15:21,885 --> 00:15:23,510 And so we could do something like this. 285 00:15:23,510 --> 00:15:30,280 286 00:15:30,280 --> 00:15:32,580 So this would be a very, very simple reducer. 287 00:15:32,580 --> 00:15:36,600 So given a state and an update, where they're both objects, 288 00:15:36,600 --> 00:15:38,190 just merge those objects. 289 00:15:38,190 --> 00:15:40,194 And so take all of the keys and states of-- you 290 00:15:40,194 --> 00:15:41,610 don't remember what the syntax is. 291 00:15:41,610 --> 00:15:45,360 It's object spread by which you take all of the key and value 292 00:15:45,360 --> 00:15:50,125 pairs of an object, and you add them to this new object that we're creating. 293 00:15:50,125 --> 00:15:51,750 And then do the same thing with update. 294 00:15:51,750 --> 00:15:55,780 Take all of its keys and value pairs, and then apply them to the same object. 295 00:15:55,780 --> 00:15:57,750 And so if there are any duplicate keys, they'll 296 00:15:57,750 --> 00:16:01,456 get overwritten by this second update. 297 00:16:01,456 --> 00:16:06,025 And so this is an example of an extremely simple reducer. 298 00:16:06,025 --> 00:16:08,400 And so let's actually play with our reducer a little bit. 299 00:16:08,400 --> 00:16:13,610 We can do something like let state start as an empty object. 300 00:16:13,610 --> 00:16:19,050 We can do state is now-- 301 00:16:19,050 --> 00:16:25,290 invoke the reducer on the old state, and that it's passing something like foo 302 00:16:25,290 --> 00:16:28,170 gets foo. 303 00:16:28,170 --> 00:16:31,920 And then now let's update the state again. 304 00:16:31,920 --> 00:16:34,670 And so that's passed into our reducer-- 305 00:16:34,670 --> 00:16:37,050 the old states, and maybe bar gets bar. 306 00:16:37,050 --> 00:16:39,810 307 00:16:39,810 --> 00:16:46,380 And lastly, let's update the state again, passes into the reducer, 308 00:16:46,380 --> 00:16:48,750 and give it now foo gets baz. 309 00:16:48,750 --> 00:16:51,310 310 00:16:51,310 --> 00:16:53,900 And so what do we expect to see back here? 311 00:16:53,900 --> 00:16:59,740 So we have state initialises an empty object. 312 00:16:59,740 --> 00:17:04,240 And then first we invoke it and passing this object that 313 00:17:04,240 --> 00:17:06,819 has a key value pair of foo and foo. 314 00:17:06,819 --> 00:17:11,329 And so when we invoke that, we have an empty object here and foo here. 315 00:17:11,329 --> 00:17:16,016 And so after line 7, our state is just foo, foo. 316 00:17:16,016 --> 00:17:17,319 How about line 8? 317 00:17:17,319 --> 00:17:23,260 Now we pass foo foo into the reducer, and also pass an update called bar bar. 318 00:17:23,260 --> 00:17:25,780 And so state is foo foo. 319 00:17:25,780 --> 00:17:26,650 Update is bar bar. 320 00:17:26,650 --> 00:17:31,210 And so we now are ended up with an object with a key of foo 321 00:17:31,210 --> 00:17:34,840 and a value of foo, a key of bar and a value of bar. 322 00:17:34,840 --> 00:17:37,460 And then lastly, we pass that object into the reducer again, 323 00:17:37,460 --> 00:17:40,570 this time with a key value pair of foo and baz. 324 00:17:40,570 --> 00:17:44,920 And so what we expect to see out of that is an object with a key of foo, 325 00:17:44,920 --> 00:17:49,239 value of baz, and a key bar with a value of bar. 326 00:17:49,239 --> 00:17:50,530 So let's go ahead and run this. 327 00:17:50,530 --> 00:17:55,840 But first, since object spread is not yet supported by node, 328 00:17:55,840 --> 00:17:59,890 let's just replace it with something like a helper function called 329 00:17:59,890 --> 00:18:05,390 merge, where it'll take a bunch of arguments-- some number of arguments. 330 00:18:05,390 --> 00:18:08,740 Let's actually just to prev and next. 331 00:18:08,740 --> 00:18:13,630 And it will do this thing called object, dot, assign, 332 00:18:13,630 --> 00:18:15,910 which is the way that we used to merge objects before. 333 00:18:15,910 --> 00:18:19,420 This object spread became a syntax. 334 00:18:19,420 --> 00:18:24,670 And so let's just assign a new object, the key value pairs of previous, 335 00:18:24,670 --> 00:18:27,160 and then the key value pairs of next. 336 00:18:27,160 --> 00:18:29,830 And then rather than doing this manually here, 337 00:18:29,830 --> 00:18:34,600 let's just merge state and update. 338 00:18:34,600 --> 00:18:37,139 So let's run this and see what we get. 339 00:18:37,139 --> 00:18:39,430 I guess nothing will happen when you run that, so let's 340 00:18:39,430 --> 00:18:41,230 just console log the state at the end. 341 00:18:41,230 --> 00:18:46,400 342 00:18:46,400 --> 00:18:48,690 And so we get what we expected. 343 00:18:48,690 --> 00:18:51,230 So we expect it to get this thing with foo baz and bar bar. 344 00:18:51,230 --> 00:18:53,210 And that's exactly what we got. 345 00:18:53,210 --> 00:18:58,490 And so to recap, all a reducer is is something 346 00:18:58,490 --> 00:19:02,960 that takes some previous state and something that we want to update it 347 00:19:02,960 --> 00:19:06,870 with and then returns a new state. 348 00:19:06,870 --> 00:19:11,460 So in our particular reducer, we chose to just merge the update into states. 349 00:19:11,460 --> 00:19:15,410 But what happens here doesn't matter, as long 350 00:19:15,410 --> 00:19:17,390 as it's returning a new state object. 351 00:19:17,390 --> 00:19:22,910 And so like I alluded to earlier, we can make our reducer even simpler 352 00:19:22,910 --> 00:19:23,840 by just doing this. 353 00:19:23,840 --> 00:19:27,660 354 00:19:27,660 --> 00:19:36,605 So if we did this, and ran it, we just get 355 00:19:36,605 --> 00:19:38,437 an empty object, which is as expected. 356 00:19:38,437 --> 00:19:41,270 Because all we're doing is we're just passing the old state backward 357 00:19:41,270 --> 00:19:43,940 and completely ignoring the update and passing an old state. 358 00:19:43,940 --> 00:19:47,570 So this is a completely valid reducer. 359 00:19:47,570 --> 00:19:51,080 It just happened to be that it doesn't do anything. 360 00:19:51,080 --> 00:19:55,790 And so instead, we made it do something by merging these objects. 361 00:19:55,790 --> 00:20:01,430 362 00:20:01,430 --> 00:20:01,930 Cool. 363 00:20:01,930 --> 00:20:06,160 So let's make our Redux model a little bit more advanced. 364 00:20:06,160 --> 00:20:09,610 So how was it responsible for invoking the reducer? 365 00:20:09,610 --> 00:20:12,040 And how do we actually manage the state? 366 00:20:12,040 --> 00:20:15,400 Because currently, it's not very good that the way 367 00:20:15,400 --> 00:20:21,160 that we're managing the state is just this state object that we're mutating. 368 00:20:21,160 --> 00:20:25,000 Why not try to wrap this up in something self-contained, like a class? 369 00:20:25,000 --> 00:20:30,919 And that's exactly what Redux does with this concept of a store. 370 00:20:30,919 --> 00:20:31,710 So what is a store? 371 00:20:31,710 --> 00:20:33,520 So as we talked about earlier, a store is 372 00:20:33,520 --> 00:20:35,790 responsible for maintaining some sort of state. 373 00:20:35,790 --> 00:20:39,390 374 00:20:39,390 --> 00:20:40,870 It does a bunch of other stuff. 375 00:20:40,870 --> 00:20:46,110 But at its core, it's just responsible for remembering what the state is. 376 00:20:46,110 --> 00:20:49,500 The way that you access that state is through this [INAUDIBLE] method 377 00:20:49,500 --> 00:20:50,480 called getState. 378 00:20:50,480 --> 00:20:52,620 And so you can invoke this method called getState, 379 00:20:52,620 --> 00:20:55,350 and it'll return the current state. 380 00:20:55,350 --> 00:20:56,730 And how do you update that state? 381 00:20:56,730 --> 00:20:58,770 Well, as we talked about earlier, the only way 382 00:20:58,770 --> 00:21:02,490 to do it is by using this thing called dispatch-- by dispatching an action 383 00:21:02,490 --> 00:21:05,250 to update the state. 384 00:21:05,250 --> 00:21:08,520 And lastly, you can add listeners that get invoked when the state changes. 385 00:21:08,520 --> 00:21:12,420 And so it wouldn't be super great of a reactive model 386 00:21:12,420 --> 00:21:16,440 if the store just updated itself and didn't tell anybody, 387 00:21:16,440 --> 00:21:19,770 because the whole point of React is that the UI will react 388 00:21:19,770 --> 00:21:23,410 to updates in the application state. 389 00:21:23,410 --> 00:21:29,490 And so what Redux does is when the application state gets updated, 390 00:21:29,490 --> 00:21:32,100 it'll run some callbacks. 391 00:21:32,100 --> 00:21:34,720 But let's not include that in our implementation for now. 392 00:21:34,720 --> 00:21:44,920 393 00:21:44,920 --> 00:21:47,440 So currently, we have this very simple reducer. 394 00:21:47,440 --> 00:21:49,570 And now let's turn it into a store. 395 00:21:49,570 --> 00:21:51,790 And so what does a store need? 396 00:21:51,790 --> 00:21:54,640 Well, it should maintain the state within itself. 397 00:21:54,640 --> 00:21:58,570 It should expose some sort of getter method called getState. 398 00:21:58,570 --> 00:22:01,270 And it should expose this method called dispatch, 399 00:22:01,270 --> 00:22:03,916 which is the way that you update these actions. 400 00:22:03,916 --> 00:22:08,266 And so let's start to do that. 401 00:22:08,266 --> 00:22:12,640 And so let's create this class called Store. 402 00:22:12,640 --> 00:22:14,290 And how do you create a store? 403 00:22:14,290 --> 00:22:21,550 Well, let's just say you pass it, maybe a reducer. 404 00:22:21,550 --> 00:22:25,270 So how does a store know how to update itself? 405 00:22:25,270 --> 00:22:27,780 And you also pass it, maybe some initial state. 406 00:22:27,780 --> 00:22:32,332 407 00:22:32,332 --> 00:22:34,040 And what should it do in the constructor? 408 00:22:34,040 --> 00:22:35,790 Well, it should remember these things. 409 00:22:35,790 --> 00:22:38,390 And so maybe it'll say this.reducer-- 410 00:22:38,390 --> 00:22:41,300 is that reducer that you passed it. 411 00:22:41,300 --> 00:22:45,830 And maybe the initial state, or the state, is that initial state. 412 00:22:45,830 --> 00:22:51,810 413 00:22:51,810 --> 00:22:52,310 Cool. 414 00:22:52,310 --> 00:22:54,570 So now we have a store. 415 00:22:54,570 --> 00:22:58,280 It's kind of useless because all it does is create this class instance, 416 00:22:58,280 --> 00:23:00,390 and you can't actually interface with it at all. 417 00:23:00,390 --> 00:23:05,300 And so let's start to add these methods by which you can interface with it. 418 00:23:05,300 --> 00:23:08,990 So first, we said you should be able to get the state by invoking 419 00:23:08,990 --> 00:23:10,770 this thing called getState. 420 00:23:10,770 --> 00:23:16,415 And so let's create this method called getState, which is pretty simple. 421 00:23:16,415 --> 00:23:19,070 422 00:23:19,070 --> 00:23:24,106 All it does is return this.state. 423 00:23:24,106 --> 00:23:26,230 And so now we're starting to make our simple store. 424 00:23:26,230 --> 00:23:27,396 We can test it a little bit. 425 00:23:27,396 --> 00:23:36,370 426 00:23:36,370 --> 00:23:40,510 Let's just pass our simple reducer, and then you'll 427 00:23:40,510 --> 00:23:44,560 see the initial state of empty. 428 00:23:44,560 --> 00:23:50,010 And then let's see what the initial state is. 429 00:23:50,010 --> 00:23:56,655 And so we can do store, dot, get the State. 430 00:23:56,655 --> 00:24:03,530 431 00:24:03,530 --> 00:24:08,660 So if we run that, we just get an empty object back, which is as expected. 432 00:24:08,660 --> 00:24:12,050 All store is currently a constructor that 433 00:24:12,050 --> 00:24:15,020 takes the reducer in an initial state, initializes 434 00:24:15,020 --> 00:24:16,704 the state to the initial state. 435 00:24:16,704 --> 00:24:18,620 And then we have no way of updating the state. 436 00:24:18,620 --> 00:24:22,560 And so when you call this.state, it just returns an empty object. 437 00:24:22,560 --> 00:24:30,900 And if we add instead past its arbitrary object like foo foo, and then ran it, 438 00:24:30,900 --> 00:24:33,840 we'll get that same object back. 439 00:24:33,840 --> 00:24:34,340 Cool. 440 00:24:34,340 --> 00:24:41,030 So not very useful yet, and so let's start to add some features to it. 441 00:24:41,030 --> 00:24:44,030 So first, and most importantly, we should have some sort of way 442 00:24:44,030 --> 00:24:45,560 to update that state. 443 00:24:45,560 --> 00:24:49,370 And the way that we do this in Redux is by dispatching an action 444 00:24:49,370 --> 00:24:54,980 or by just invoking this method called dispatch with some way of updating. 445 00:24:54,980 --> 00:24:59,000 And so the way that we've been doing this thus far 446 00:24:59,000 --> 00:25:02,640 is by just passing an object that we want merged into a state. 447 00:25:02,640 --> 00:25:04,310 And so let's do that. 448 00:25:04,310 --> 00:25:07,400 So let's have this thing called dispatch. 449 00:25:07,400 --> 00:25:08,080 We pass it. 450 00:25:08,080 --> 00:25:11,790 Well, we pass it some sort of update. 451 00:25:11,790 --> 00:25:13,230 And what does it do? 452 00:25:13,230 --> 00:25:19,850 Well, it should update the current state to be what? 453 00:25:19,850 --> 00:25:21,770 We want to run this reducer function. 454 00:25:21,770 --> 00:25:24,850 455 00:25:24,850 --> 00:25:26,000 And which reducer function? 456 00:25:26,000 --> 00:25:29,450 Well, whichever one that we passed in the original constructor 457 00:25:29,450 --> 00:25:31,195 and stored as this.reducer. 458 00:25:31,195 --> 00:25:36,890 So let's invoke that with the current state, and then any update 459 00:25:36,890 --> 00:25:40,070 that we want to pass it. 460 00:25:40,070 --> 00:25:43,440 And that's pretty much it. 461 00:25:43,440 --> 00:25:49,190 And so now down here, rather than having to handle this ourselves-- 462 00:25:49,190 --> 00:25:55,400 and by this I mean replacing the old state with the reducer, 463 00:25:55,400 --> 00:25:58,160 with value after passing it through the reducer-- 464 00:25:58,160 --> 00:26:01,310 that's now abstracted away from us using this thing called a store. 465 00:26:01,310 --> 00:26:07,357 And so now we can just do store, dot, dispatch this object. 466 00:26:07,357 --> 00:26:08,440 And the same goes to here. 467 00:26:08,440 --> 00:26:23,710 468 00:26:23,710 --> 00:26:26,100 And so now, we're doing things a little bit differently. 469 00:26:26,100 --> 00:26:29,430 So rather than creating the state ourselves 470 00:26:29,430 --> 00:26:36,906 and manually going through and replacing state with the output of the reducer 471 00:26:36,906 --> 00:26:39,780 and passing in the old state, now that's handled for us by this thing 472 00:26:39,780 --> 00:26:40,432 called a store. 473 00:26:40,432 --> 00:26:41,640 And how is it handled for us? 474 00:26:41,640 --> 00:26:48,180 Well, the store is actually storing the state as part of its class. 475 00:26:48,180 --> 00:26:50,910 And so the state gets initialized to some initial state. 476 00:26:50,910 --> 00:26:55,410 And every time we dispatch an action or dispatch an update, 477 00:26:55,410 --> 00:26:56,430 it handles that for us. 478 00:26:56,430 --> 00:26:58,290 It remembers what the reducer is. 479 00:26:58,290 --> 00:27:01,180 It knows how it should update its own state by just doing this, 480 00:27:01,180 --> 00:27:05,302 dot, state, equals the old state, applying an update through the reducer. 481 00:27:05,302 --> 00:27:06,510 But we don't care about that. 482 00:27:06,510 --> 00:27:08,640 We don't need to know the implementation details. 483 00:27:08,640 --> 00:27:09,750 We don't really care. 484 00:27:09,750 --> 00:27:15,240 All we care is that we just pass this store.dispatch function, 485 00:27:15,240 --> 00:27:17,190 some update that we want to apply. 486 00:27:17,190 --> 00:27:19,530 And it goes ahead and does the rest of it. 487 00:27:19,530 --> 00:27:22,470 We don't even care that state is stored as an object. 488 00:27:22,470 --> 00:27:24,240 That's all just abstracted away. 489 00:27:24,240 --> 00:27:27,210 All that we care about is we update the state 490 00:27:27,210 --> 00:27:30,360 by passing something into dispatch. 491 00:27:30,360 --> 00:27:35,370 And we get the state back by invoking this thing called getState. 492 00:27:35,370 --> 00:27:38,789 We don't care that the state is just stored on the constructor. 493 00:27:38,789 --> 00:27:40,830 For all we know, maybe it's a tree, or maybe it's 494 00:27:40,830 --> 00:27:43,650 some weird data structure for performance. 495 00:27:43,650 --> 00:27:45,470 It doesn't matter. 496 00:27:45,470 --> 00:27:48,090 All that we care about is the API for this store. 497 00:27:48,090 --> 00:27:52,170 And this API is just getting the state and dispatching state updates. 498 00:27:52,170 --> 00:27:53,760 And so let's make sure it works. 499 00:27:53,760 --> 00:27:56,940 500 00:27:56,940 --> 00:28:00,679 So we create a new store down here by saying, give me a new store. 501 00:28:00,679 --> 00:28:03,470 I'm going to pass it, the reducer function that we defined up here. 502 00:28:03,470 --> 00:28:07,097 So let's actually just move this down. 503 00:28:07,097 --> 00:28:08,055 And maybe this as well. 504 00:28:08,055 --> 00:28:12,100 505 00:28:12,100 --> 00:28:15,330 So now, let's just not care about the implementation details of store. 506 00:28:15,330 --> 00:28:17,830 All that we care about is we define this thing called merge, 507 00:28:17,830 --> 00:28:19,230 which merges objects. 508 00:28:19,230 --> 00:28:23,710 We define a reducer which takes some states and some update, 509 00:28:23,710 --> 00:28:26,050 and applies the update by merging it in. 510 00:28:26,050 --> 00:28:30,550 And then we create that new store with that reducer and some initial value 511 00:28:30,550 --> 00:28:31,180 called foo foo. 512 00:28:31,180 --> 00:28:36,610 And let's, for now, actually just not pass an initial value at all. 513 00:28:36,610 --> 00:28:39,350 And let's see what happens. 514 00:28:39,350 --> 00:28:43,900 And so we dispatch a few updates, and then now let's 515 00:28:43,900 --> 00:28:51,080 log some initials, or the state after those dispatches. 516 00:28:51,080 --> 00:28:52,830 And so we get back what we wanted. 517 00:28:52,830 --> 00:28:58,109 We get back foo baz, bar bar, which is the same thing as up here. 518 00:28:58,109 --> 00:28:59,400 And what's the main difference? 519 00:28:59,400 --> 00:29:02,940 Well, the main difference is that in reducer, we 520 00:29:02,940 --> 00:29:04,900 had to handle the updates ourselves. 521 00:29:04,900 --> 00:29:11,310 We had to handle passing in to reducer the old state and the new updates. 522 00:29:11,310 --> 00:29:21,040 And in this new file called Store, we no longer care about those things. 523 00:29:21,040 --> 00:29:25,030 We just care that we have a new store, and we're passing a new reducer. 524 00:29:25,030 --> 00:29:29,380 And we're just dispatching some additional changes. 525 00:29:29,380 --> 00:29:32,160 526 00:29:32,160 --> 00:29:32,990 Cool. 527 00:29:32,990 --> 00:29:36,140 And so this is not really super helpful for us right now. 528 00:29:36,140 --> 00:29:37,785 All it does is merge some objects. 529 00:29:37,785 --> 00:29:41,610 But let's actually modify this such that it will help us. 530 00:29:41,610 --> 00:29:45,650 And so in previous weeks, what we've been working on is this contacts app. 531 00:29:45,650 --> 00:29:50,330 And so I changed a few things from last week, or couple weeks ago to this week, 532 00:29:50,330 --> 00:29:53,990 namely that the login screen is gone and the asynchronous request 533 00:29:53,990 --> 00:29:55,820 for fetching the contacts is gone. 534 00:29:55,820 --> 00:29:58,520 And so I just reverted the app to where it 535 00:29:58,520 --> 00:30:02,920 was before we add asynchronous actions. 536 00:30:02,920 --> 00:30:06,190 And so what do we care about in this simple application? 537 00:30:06,190 --> 00:30:09,200 Well, we care about the context, obviously. 538 00:30:09,200 --> 00:30:15,170 We care about maybe adding new contacts by using this Add button in the top. 539 00:30:15,170 --> 00:30:16,730 And we kind of care about the user. 540 00:30:16,730 --> 00:30:22,340 And so before we had this login page where a user would log in-- 541 00:30:22,340 --> 00:30:25,100 and presumably we should be storing some sort of token 542 00:30:25,100 --> 00:30:27,050 or store the fact that the users logged in-- 543 00:30:27,050 --> 00:30:30,280 and so we need to care about the contacts, 544 00:30:30,280 --> 00:30:33,390 and we need to care about some concept of having a user-user app, 545 00:30:33,390 --> 00:30:35,490 so we can tell if they're logged in or not. 546 00:30:35,490 --> 00:30:38,800 And so let's use what we've implemented in Redux thus far 547 00:30:38,800 --> 00:30:40,550 to actually keep track of that information 548 00:30:40,550 --> 00:30:43,674 in Redux, rather than having to do it ourself scattered throughout our app. 549 00:30:43,674 --> 00:30:59,550 550 00:30:59,550 --> 00:31:04,650 So currently our store takes a reducer in an initial state. 551 00:31:04,650 --> 00:31:05,780 It stores those things. 552 00:31:05,780 --> 00:31:08,940 It gives us this thing called getState, which returns our state, 553 00:31:08,940 --> 00:31:14,160 and gives us a method called dispatch which applies any updates that we 554 00:31:14,160 --> 00:31:16,275 pass it to our state. 555 00:31:16,275 --> 00:31:18,150 And so we don't have to change anything there 556 00:31:18,150 --> 00:31:20,670 for the context of our contacts app. 557 00:31:20,670 --> 00:31:23,640 Though we do have to change this reducer. 558 00:31:23,640 --> 00:31:27,320 So presumably, if we want to update-- 559 00:31:27,320 --> 00:31:28,980 maybe we want to add a contact. 560 00:31:28,980 --> 00:31:32,260 The way that we would do that would be appending that to an array. 561 00:31:32,260 --> 00:31:34,140 And so there's not really a convenient way 562 00:31:34,140 --> 00:31:38,940 to do this with our current reducers, since it's just merging objects. 563 00:31:38,940 --> 00:31:42,960 So let's actually implement a reducer that will. 564 00:31:42,960 --> 00:31:53,850 So say we-- let's call it the contacts reducer. 565 00:31:53,850 --> 00:31:58,440 And the contacts reducer, or contact reducer, takes the state 566 00:31:58,440 --> 00:32:01,290 and presumably the state is all the old contacts, 567 00:32:01,290 --> 00:32:05,167 and rather than passing an update, let's just pass it a new contact. 568 00:32:05,167 --> 00:32:07,700 569 00:32:07,700 --> 00:32:09,270 And what should this do? 570 00:32:09,270 --> 00:32:13,820 So state, presumably, is just a list of old contacts. 571 00:32:13,820 --> 00:32:21,800 And so let's just spread those old contacts, 572 00:32:21,800 --> 00:32:25,640 and then add a new content at the end. 573 00:32:25,640 --> 00:32:29,330 And there's our reducer for our contacts. 574 00:32:29,330 --> 00:32:34,380 How about four-hour user? 575 00:32:34,380 --> 00:32:36,650 So maybe we should have-- 576 00:32:36,650 --> 00:32:40,250 how should we keep track of our user? 577 00:32:40,250 --> 00:32:43,370 Or more importantly, what is important to know about our user? 578 00:32:43,370 --> 00:32:47,420 Maybe something about their username, maybe whether they are logged in 579 00:32:47,420 --> 00:32:52,380 or not, maybe some other keys which have values. 580 00:32:52,380 --> 00:32:55,780 And so what's the way that we generally store key value pairs in JavaScript? 581 00:32:55,780 --> 00:32:57,590 It's usually just a simple array. 582 00:32:57,590 --> 00:32:59,970 I mean a simple object. 583 00:32:59,970 --> 00:33:03,920 So let's have this thing called a userReducer, which takes 584 00:33:03,920 --> 00:33:09,530 an old state and maybe an update again. 585 00:33:09,530 --> 00:33:12,000 And how are we going to handle this? 586 00:33:12,000 --> 00:33:14,121 Well, we'll just apply the update to this state. 587 00:33:14,121 --> 00:33:16,370 So it's basically the same as our reducer from before. 588 00:33:16,370 --> 00:33:21,850 We'll just merge into the old state that update. 589 00:33:21,850 --> 00:33:22,350 Cool. 590 00:33:22,350 --> 00:33:24,980 So now we have two separate reducers. 591 00:33:24,980 --> 00:33:29,210 One handles any updates for contacts. 592 00:33:29,210 --> 00:33:33,440 One handles any updates for a user. 593 00:33:33,440 --> 00:33:40,460 And so how are we going to apply that for our store as implemented? 594 00:33:40,460 --> 00:33:43,430 Because the store right now only takes a single reducer. 595 00:33:43,430 --> 00:33:48,225 It doesn't expect a reducer for contacts, a reducer for users, 596 00:33:48,225 --> 00:33:52,730 a reducer for metadata, a reducer for any other stuff that we want to store. 597 00:33:52,730 --> 00:33:54,480 It only expects one. 598 00:33:54,480 --> 00:33:58,640 And so we actually have to combine our reducers into just a singular reducer. 599 00:33:58,640 --> 00:34:02,420 And so if you remember, when we were talking about the pillars of Redux, 600 00:34:02,420 --> 00:34:05,585 everything is stored in one singular store, so one big object. 601 00:34:05,585 --> 00:34:10,489 But right now, we have two separate things 602 00:34:10,489 --> 00:34:15,380 that track our application state, one for contacts and one for users. 603 00:34:15,380 --> 00:34:18,949 And so how might we go about combining those reducers such 604 00:34:18,949 --> 00:34:25,449 that we have just one reducer or one source of truth for our app? 605 00:34:25,449 --> 00:34:34,540 Well, the reducer is going to just take a state and some update, 606 00:34:34,540 --> 00:34:38,290 just like all of our other reducers. 607 00:34:38,290 --> 00:34:42,909 And it's going to have to return some new state. 608 00:34:42,909 --> 00:34:49,130 And so we have to somehow tell, via this update, what we should be changing. 609 00:34:49,130 --> 00:34:52,449 So we're starting to run into a little bit of trouble here. 610 00:34:52,449 --> 00:35:03,290 In our last iteration, we were just passing an object to this dispatch. 611 00:35:03,290 --> 00:35:09,740 So its object just gets blindly merged into our state in our store. 612 00:35:09,740 --> 00:35:12,140 But now our store is a little bit complicated. 613 00:35:12,140 --> 00:35:16,200 As soon as we're hitting a real world use case, 614 00:35:16,200 --> 00:35:18,560 now we have multiple different keys in our store. 615 00:35:18,560 --> 00:35:22,880 And it's nontrivial how we're going to know exactly what we should update. 616 00:35:22,880 --> 00:35:29,480 If we just pass something like foo foo into our new store, 617 00:35:29,480 --> 00:35:33,530 how do we know whether that foo foo is an update for user, 618 00:35:33,530 --> 00:35:36,380 or foo foo is a new contact? 619 00:35:36,380 --> 00:35:39,800 We're starting to run into the limitations of how 620 00:35:39,800 --> 00:35:42,360 we've implemented our current reducer. 621 00:35:42,360 --> 00:35:43,610 And so how does Redux? 622 00:35:43,610 --> 00:35:45,130 Actually solve this? 623 00:35:45,130 --> 00:35:48,620 Well, through these things called actions. 624 00:35:48,620 --> 00:35:51,440 So an action is basically just a piece of data 625 00:35:51,440 --> 00:35:56,420 that contains all of the information required to make a state update. 626 00:35:56,420 --> 00:36:03,840 And so in our previous store implementation, 627 00:36:03,840 --> 00:36:06,800 this is true about our current update. 628 00:36:06,800 --> 00:36:12,290 Everything that we needed to update our state is passed as an argument 629 00:36:12,290 --> 00:36:13,370 to dispatch. 630 00:36:13,370 --> 00:36:17,210 So this could be considered an action, because it has everything that we 631 00:36:17,210 --> 00:36:19,970 need to update our state appropriately. 632 00:36:19,970 --> 00:36:22,620 But now we're starting to hit a limitation when 633 00:36:22,620 --> 00:36:24,980 we have a more complex store like this. 634 00:36:24,980 --> 00:36:27,680 We can't just pass an object like foo foo, 635 00:36:27,680 --> 00:36:31,460 because there's no longer enough information 636 00:36:31,460 --> 00:36:34,400 to make that full-state update. 637 00:36:34,400 --> 00:36:36,120 And so how are we going to do that? 638 00:36:36,120 --> 00:36:40,310 Well, generally actions are objects with the type key. 639 00:36:40,310 --> 00:36:45,250 That didn't necessarily have to be true in our naive implementation of store. 640 00:36:45,250 --> 00:36:47,210 But now it makes more sense to have an object, 641 00:36:47,210 --> 00:36:51,080 because we need more key value pairs. 642 00:36:51,080 --> 00:36:56,540 Usually, this object has a key called type. 643 00:36:56,540 --> 00:36:59,750 Or in other words, what are we doing here? 644 00:36:59,750 --> 00:37:02,630 Like, what update are we making? 645 00:37:02,630 --> 00:37:04,570 What should we be updating? 646 00:37:04,570 --> 00:37:09,500 And so there actually is a loose spec for what 647 00:37:09,500 --> 00:37:12,592 is considered an action in Flux. 648 00:37:12,592 --> 00:37:14,270 And so let's go ahead and open that up. 649 00:37:14,270 --> 00:37:19,910 And we see here a general guideline to this thing called a standard action, 650 00:37:19,910 --> 00:37:24,770 or an action that we should be using universally for all 651 00:37:24,770 --> 00:37:26,960 of our Flux or Redux applications. 652 00:37:26,960 --> 00:37:29,350 And so the motivation behind that is that it's 653 00:37:29,350 --> 00:37:32,600 a lot easier to work with actions if we can make certain assumptions about how 654 00:37:32,600 --> 00:37:34,770 they are shaped. 655 00:37:34,770 --> 00:37:37,550 Because it wouldn't really make sense if in one application 656 00:37:37,550 --> 00:37:41,810 we have our actions as objects, and maybe in a separate application 657 00:37:41,810 --> 00:37:42,502 we have a raise. 658 00:37:42,502 --> 00:37:44,210 In a separate application, it's a number. 659 00:37:44,210 --> 00:37:46,530 And maybe in another application it's a string. 660 00:37:46,530 --> 00:37:50,561 And so as we scale up, we want to have some sort of uniformity 661 00:37:50,561 --> 00:37:51,560 across our applications. 662 00:37:51,560 --> 00:37:55,620 And so no matter what application we go to maintain, we know, hey, 663 00:37:55,620 --> 00:37:58,680 our application actions should all look the same. 664 00:37:58,680 --> 00:38:02,150 They should have some sort of key that tells me the type of update 665 00:38:02,150 --> 00:38:04,610 that we're doing here. 666 00:38:04,610 --> 00:38:10,280 And so the goal of these actions is that they should be human-friendly, 667 00:38:10,280 --> 00:38:13,740 so Flux standard actions should be easy to read, easy to write. 668 00:38:13,740 --> 00:38:15,530 They should be useful. 669 00:38:15,530 --> 00:38:19,460 Presumably, we're not just creating these arbitrary things 670 00:38:19,460 --> 00:38:20,460 for the sake of it. 671 00:38:20,460 --> 00:38:23,540 We want them to actually have a use case, to be useful for application. 672 00:38:23,540 --> 00:38:25,910 And lastly, we want them to be simple. 673 00:38:25,910 --> 00:38:29,750 There's no reason to add additional complexity when we don't need to. 674 00:38:29,750 --> 00:38:33,570 And so a basic action might look like this. 675 00:38:33,570 --> 00:38:39,300 So we have a type that designates what exactly should this action be doing. 676 00:38:39,300 --> 00:38:42,696 We have a payload, or in other words, like, OK, 677 00:38:42,696 --> 00:38:44,070 I know I should be updating this. 678 00:38:44,070 --> 00:38:46,710 What should I actually update it with? 679 00:38:46,710 --> 00:38:50,090 And so, generally, actions are objects with the type key, 680 00:38:50,090 --> 00:38:54,390 and maybe they have other things like an air property, payload, or meta. 681 00:38:54,390 --> 00:38:56,990 And for our particular implementation, we'll 682 00:38:56,990 --> 00:39:01,550 be creating objects with a type and a payload. 683 00:39:01,550 --> 00:39:03,910 And so let's go ahead and do that now. 684 00:39:03,910 --> 00:39:16,331 685 00:39:16,331 --> 00:39:16,830 All right. 686 00:39:16,830 --> 00:39:23,589 So now we know that when we pass in this argument to dispatch, 687 00:39:23,589 --> 00:39:25,630 we need to include a little bit more information. 688 00:39:25,630 --> 00:39:29,760 It's not enough just to have an object with foo foo. 689 00:39:29,760 --> 00:39:36,330 So let's actually pass a more complex object 690 00:39:36,330 --> 00:39:42,642 where the payload ends up being foo foo, but that's passing a type, 691 00:39:42,642 --> 00:39:44,850 so that we know exactly what we should be doing here. 692 00:39:44,850 --> 00:39:52,610 And maybe the type is something like update the user. 693 00:39:52,610 --> 00:39:54,770 And maybe down here, we do the same thing. 694 00:39:54,770 --> 00:40:02,330 695 00:40:02,330 --> 00:40:08,882 We want to update that user with a payload of that bar bar, 696 00:40:08,882 --> 00:40:10,090 and the same thing done here. 697 00:40:10,090 --> 00:40:19,790 698 00:40:19,790 --> 00:40:22,520 So now it looks a little bit more complicated. 699 00:40:22,520 --> 00:40:24,410 Our actions are no longer simple objects. 700 00:40:24,410 --> 00:40:26,660 Now they are a nested object where they have 701 00:40:26,660 --> 00:40:30,090 a type that is letting us know that we should be updating the user. 702 00:40:30,090 --> 00:40:32,690 And it has a payload, which is just letting us know 703 00:40:32,690 --> 00:40:34,987 how we should be updating that user. 704 00:40:34,987 --> 00:40:36,320 And there's a syntax error here. 705 00:40:36,320 --> 00:40:39,260 706 00:40:39,260 --> 00:40:42,590 And so now let's actually look for that type in our reducer. 707 00:40:42,590 --> 00:40:45,980 And so now, rather than passing a state and update to a user, 708 00:40:45,980 --> 00:40:49,150 now we're passing a state and an action. 709 00:40:49,150 --> 00:40:54,530 And so now we have some sort of signal about what part of the state 710 00:40:54,530 --> 00:40:55,820 we should be updating. 711 00:40:55,820 --> 00:41:01,550 And so let's do if action, dot, type is this thing called 712 00:41:01,550 --> 00:41:05,570 Update User, what should we do here? 713 00:41:05,570 --> 00:41:08,880 714 00:41:08,880 --> 00:41:13,940 Well, we know exactly how we want to update the user. 715 00:41:13,940 --> 00:41:17,570 It's dictated by this userReducer. 716 00:41:17,570 --> 00:41:19,730 And we know how we want to update the contact. 717 00:41:19,730 --> 00:41:21,030 We don't. 718 00:41:21,030 --> 00:41:33,460 And so let's actually return here an object that maintains the old shape. 719 00:41:33,460 --> 00:41:36,350 So the old state is intact. 720 00:41:36,350 --> 00:41:38,997 And now we want to update the user key. 721 00:41:38,997 --> 00:41:40,580 And the user key, how do we update it? 722 00:41:40,580 --> 00:41:43,087 Well, we pass it into the userReducer. 723 00:41:43,087 --> 00:41:45,890 724 00:41:45,890 --> 00:41:48,560 And what do we pass into the userReducer? 725 00:41:48,560 --> 00:41:53,350 So right now, the userReducer expects a state in update, 726 00:41:53,350 --> 00:41:58,200 and it's going to merge the update into the old state. 727 00:41:58,200 --> 00:42:00,620 And so what states are we passing onto user-reducer here? 728 00:42:00,620 --> 00:42:02,870 Is it the state here? 729 00:42:02,870 --> 00:42:03,800 Not really, right? 730 00:42:03,800 --> 00:42:06,230 Because the state here is responding to what state? 731 00:42:06,230 --> 00:42:07,940 It's responding to the entire application 732 00:42:07,940 --> 00:42:12,350 state, that includes all of the contacts that we have and the user. 733 00:42:12,350 --> 00:42:15,650 And the userReducer really doesn't care about any contacts. 734 00:42:15,650 --> 00:42:18,320 It only cares about the user itself. 735 00:42:18,320 --> 00:42:21,440 And so rather than passing the entire application state there, 736 00:42:21,440 --> 00:42:23,770 we only care about the user state. 737 00:42:23,770 --> 00:42:27,356 And so we can just do state, dot, user here. 738 00:42:27,356 --> 00:42:28,730 And how do you want to update it? 739 00:42:28,730 --> 00:42:30,271 Well, it's just that actions payload. 740 00:42:30,271 --> 00:42:34,650 741 00:42:34,650 --> 00:42:38,317 And then if the action type isn't update user, just return the old state. 742 00:42:38,317 --> 00:42:42,990 743 00:42:42,990 --> 00:42:45,790 So there's going to be invalid syntax here. 744 00:42:45,790 --> 00:42:57,440 So let's just use our merge helper function here, 745 00:42:57,440 --> 00:43:03,052 where we're merging this new object into state. 746 00:43:03,052 --> 00:43:05,760 So it's basically the same thing that we had written before, just 747 00:43:05,760 --> 00:43:08,380 in different syntax. 748 00:43:08,380 --> 00:43:10,980 So can we all follow what happened here? 749 00:43:10,980 --> 00:43:16,320 So we create a store, and we pass in a reducer. 750 00:43:16,320 --> 00:43:17,690 What is the reducer? 751 00:43:17,690 --> 00:43:21,030 Well, the reducer, it takes a state, and it takes an action. 752 00:43:21,030 --> 00:43:26,850 And what's the logic behind the way that we update the state? 753 00:43:26,850 --> 00:43:29,550 Well, if the action has a type called Update User, 754 00:43:29,550 --> 00:43:31,320 we're going to update the user. 755 00:43:31,320 --> 00:43:33,390 And we don't care about any other types. 756 00:43:33,390 --> 00:43:38,970 If it passes any other type, then we're just going to return the state as is. 757 00:43:38,970 --> 00:43:42,690 But what exactly happens when you passed in something 758 00:43:42,690 --> 00:43:46,330 where the type is update user? 759 00:43:46,330 --> 00:43:51,547 Well, we call that userReducer with the payload. 760 00:43:51,547 --> 00:43:52,380 What is the payload? 761 00:43:52,380 --> 00:43:55,230 Well, it's just any update that we want to do. 762 00:43:55,230 --> 00:43:56,880 Why are we calling it payload? 763 00:43:56,880 --> 00:44:02,790 Well, that's just the convention as dictated by Flux [INAUDIBLE] 764 00:44:02,790 --> 00:44:05,820 And so what happens in this userReducer? 765 00:44:05,820 --> 00:44:09,320 Well, we pass it the old state of the user. 766 00:44:09,320 --> 00:44:12,090 And we pass it the update that we want to make. 767 00:44:12,090 --> 00:44:14,220 And we don't really care what happens there. 768 00:44:14,220 --> 00:44:19,470 It just happens to be the case that it merges. 769 00:44:19,470 --> 00:44:24,510 And so what do we expect to happen after we dispatch these three actions? 770 00:44:24,510 --> 00:44:26,370 We update the user with foo foo. 771 00:44:26,370 --> 00:44:28,170 We update the user with bar bar. 772 00:44:28,170 --> 00:44:30,780 We update the user again with foo baz. 773 00:44:30,780 --> 00:44:34,290 And we expect to see exactly what we saw before. 774 00:44:34,290 --> 00:44:39,800 That is an object with a key foo with the value baz, 775 00:44:39,800 --> 00:44:42,720 and a key bar with the value bar. 776 00:44:42,720 --> 00:44:46,860 Is that what we actually get back, when we call store, dot, getState? 777 00:44:46,860 --> 00:44:50,590 778 00:44:50,590 --> 00:44:58,790 I don't think that's going to be the case, because there's a syntax error. 779 00:44:58,790 --> 00:45:04,640 780 00:45:04,640 --> 00:45:08,829 This error here is because state, right now, is undefined. 781 00:45:08,829 --> 00:45:10,870 And so there's no such thing as state, dot, user. 782 00:45:10,870 --> 00:45:14,450 And so we should probably pass in some sort of default user or default 783 00:45:14,450 --> 00:45:16,391 application state. 784 00:45:16,391 --> 00:45:26,590 And so let's just say the default state is-- 785 00:45:26,590 --> 00:45:28,690 let's create a const called Default State. 786 00:45:28,690 --> 00:45:32,110 787 00:45:32,110 --> 00:45:35,680 And let's say the user is just an empty object, 788 00:45:35,680 --> 00:45:38,420 and the contacts are an empty array. 789 00:45:38,420 --> 00:45:42,460 790 00:45:42,460 --> 00:45:45,070 And let's pass that in when we create our new store. 791 00:45:45,070 --> 00:45:49,649 792 00:45:49,649 --> 00:45:51,440 So now we've passed in some default states. 793 00:45:51,440 --> 00:45:55,840 So when we do state, dot, user, we're not getting an error there. 794 00:45:55,840 --> 00:45:58,750 795 00:45:58,750 --> 00:45:59,750 And what do we get back? 796 00:45:59,750 --> 00:46:03,430 We don't get back what we were getting back earlier. 797 00:46:03,430 --> 00:46:07,990 And what we're getting back earlier was just 798 00:46:07,990 --> 00:46:14,410 this, an object with a couple of key values where it's foo baz and bar bar. 799 00:46:14,410 --> 00:46:16,780 Now we're getting back this thing. 800 00:46:16,780 --> 00:46:23,170 We see that object within our state, but that's not our entire state. 801 00:46:23,170 --> 00:46:27,514 That object is contained within a part of our state called User. 802 00:46:27,514 --> 00:46:29,680 And there's also a separate part of our state called 803 00:46:29,680 --> 00:46:32,440 Contacts, which is an empty array-- 804 00:46:32,440 --> 00:46:35,260 which makes sense when you think about what we just did. 805 00:46:35,260 --> 00:46:45,290 806 00:46:45,290 --> 00:46:48,840 Our application is no longer just a single object. 807 00:46:48,840 --> 00:46:52,390 It's now an object that looks like this. 808 00:46:52,390 --> 00:46:57,190 We have a key that corresponds to our user information. 809 00:46:57,190 --> 00:47:01,170 You have a key that corresponds to all of the contacts that we have. 810 00:47:01,170 --> 00:47:03,957 And so when we're dispatching actions that update the user, 811 00:47:03,957 --> 00:47:05,040 they're updating the user. 812 00:47:05,040 --> 00:47:08,790 But there's still a whole separate part of our application state 813 00:47:08,790 --> 00:47:10,260 that corresponds to those contacts. 814 00:47:10,260 --> 00:47:14,320 815 00:47:14,320 --> 00:47:21,900 And so now let's strengthen our store by allowing us to add contacts. 816 00:47:21,900 --> 00:47:23,316 How might we want to do that? 817 00:47:23,316 --> 00:47:27,440 818 00:47:27,440 --> 00:47:29,960 Maybe we should add a new type. 819 00:47:29,960 --> 00:47:33,540 So remember, at the core of Redux is the reducer, 820 00:47:33,540 --> 00:47:39,290 which handles the logic between receiving the action 821 00:47:39,290 --> 00:47:41,510 and updating the state of our application. 822 00:47:41,510 --> 00:47:45,140 And so in our reducer here, we're going to add more logic 823 00:47:45,140 --> 00:47:48,890 for when we want to add a contact. 824 00:47:48,890 --> 00:47:52,370 And how do we know when we're trying to add a contact? 825 00:47:52,370 --> 00:47:56,310 Well, it's dictated by the type of action that we're receiving. 826 00:47:56,310 --> 00:48:08,860 So if we get a new action type, and let's call this Update Contact, 827 00:48:08,860 --> 00:48:11,110 now we want to do something different. 828 00:48:11,110 --> 00:48:14,450 Now, we don't really care about any update with the user. 829 00:48:14,450 --> 00:48:18,370 Now, we only care about updating our contacts. 830 00:48:18,370 --> 00:48:20,650 And so what might we want to do? 831 00:48:20,650 --> 00:48:25,820 Well, let's return a new state. 832 00:48:25,820 --> 00:48:28,245 833 00:48:28,245 --> 00:48:29,870 And what does that new state look like? 834 00:48:29,870 --> 00:48:33,820 Well, let's update the old state, so merge in old state 835 00:48:33,820 --> 00:48:37,790 this new thing where contacts are updated. 836 00:48:37,790 --> 00:48:41,040 And so how are you going to update contacts? 837 00:48:41,040 --> 00:48:47,290 What logic dictates how we want to update our contact? 838 00:48:47,290 --> 00:48:54,037 We could just do, give me the old contacts and add a new contacts. 839 00:48:54,037 --> 00:48:56,120 And where is the new contact action, dot, payload? 840 00:48:56,120 --> 00:48:59,850 841 00:48:59,850 --> 00:49:02,770 But this logic is already written somewhere in our app. 842 00:49:02,770 --> 00:49:05,480 We already declared this thing called a contactReducer, which 843 00:49:05,480 --> 00:49:08,250 does this exact thing. 844 00:49:08,250 --> 00:49:13,390 What it does is it expects the state of the old contacts and a new contact. 845 00:49:13,390 --> 00:49:16,470 And so we abstracted that information away into this thing 846 00:49:16,470 --> 00:49:22,020 called the contactReducer, which expects the old state of contacts. 847 00:49:22,020 --> 00:49:27,060 And so we don't want to pass just the entire application state. 848 00:49:27,060 --> 00:49:29,580 We only care about the contacts portion of it. 849 00:49:29,580 --> 00:49:32,530 850 00:49:32,530 --> 00:49:35,280 And then we pass the payload. 851 00:49:35,280 --> 00:49:46,210 852 00:49:46,210 --> 00:49:49,950 So very similar to what we did up here, up here 853 00:49:49,950 --> 00:49:52,680 when we receive an action called update our user, 854 00:49:52,680 --> 00:49:57,070 we go ahead and invoke the userReducer on that user. 855 00:49:57,070 --> 00:49:59,632 And when we receive an action to update the contact, 856 00:49:59,632 --> 00:50:02,090 now we just do the same thing but for the contacts instead. 857 00:50:02,090 --> 00:50:04,980 858 00:50:04,980 --> 00:50:08,160 So now let's test this out. 859 00:50:08,160 --> 00:50:13,690 So now let's call store, dot, dispatch, this thing 860 00:50:13,690 --> 00:50:23,110 with a type of Update Contact, and a payload of name-- 861 00:50:23,110 --> 00:50:26,710 862 00:50:26,710 --> 00:50:33,610 my name-- and number of some arbitrary string. 863 00:50:33,610 --> 00:50:40,850 864 00:50:40,850 --> 00:50:44,170 So now we just sent a separate action. 865 00:50:44,170 --> 00:50:48,160 And so now, if you notice, this action has the same shape as the action 866 00:50:48,160 --> 00:50:49,090 up here. 867 00:50:49,090 --> 00:50:53,000 It's a type and a payload. 868 00:50:53,000 --> 00:50:55,450 Now the type is Update Contact, and the payload-- 869 00:50:55,450 --> 00:51:00,942 rather than being the update for a user-- is actually the contact itself. 870 00:51:00,942 --> 00:51:03,900 And then our reducer knows exactly what to do with all of these things. 871 00:51:03,900 --> 00:51:06,066 And so now let's just run this and see what happens. 872 00:51:06,066 --> 00:51:11,680 873 00:51:11,680 --> 00:51:15,270 So now our state got updated. 874 00:51:15,270 --> 00:51:18,960 So our user still has the information that we expect the user to have. 875 00:51:18,960 --> 00:51:20,340 But now we have some contacts. 876 00:51:20,340 --> 00:51:24,090 Now it's an array that includes me and my phone number. 877 00:51:24,090 --> 00:51:27,550 Don't call it, because it's not actually my phone number. 878 00:51:27,550 --> 00:51:32,040 And so what happens when you try to add a separate user? 879 00:51:32,040 --> 00:51:37,210 Maybe our contact has two friends of the exact same name and the same phone 880 00:51:37,210 --> 00:51:37,710 number. 881 00:51:37,710 --> 00:51:44,880 882 00:51:44,880 --> 00:51:49,590 So now our application has two contacts in the contacts. 883 00:51:49,590 --> 00:51:52,840 And they just happen to be the same people because I cut and paste. 884 00:51:52,840 --> 00:51:53,820 Cool. 885 00:51:53,820 --> 00:51:57,150 So now we have some sort of store that's maintaining 886 00:51:57,150 --> 00:51:59,630 all of our application information. 887 00:51:59,630 --> 00:52:02,110 But admittedly, it's not super clean. 888 00:52:02,110 --> 00:52:05,120 889 00:52:05,120 --> 00:52:07,560 So let's clean it up a little bit. 890 00:52:07,560 --> 00:52:13,974 So right now, we have our action types hardcoded. 891 00:52:13,974 --> 00:52:15,890 We can keep them hardcoded, but let's actually 892 00:52:15,890 --> 00:52:17,306 create a variable for our actions. 893 00:52:17,306 --> 00:52:19,940 That way we can easily keep track of our available actions. 894 00:52:19,940 --> 00:52:23,610 895 00:52:23,610 --> 00:52:33,320 So let's just create this thing called Update User and call it Update User. 896 00:52:33,320 --> 00:52:39,650 And same thing, let's create a const for our action called Update Contact. 897 00:52:39,650 --> 00:52:47,351 898 00:52:47,351 --> 00:52:50,475 And now, rather than hardcoding this string here, we can use that constant. 899 00:52:50,475 --> 00:53:01,060 900 00:53:01,060 --> 00:53:03,620 And then same here. 901 00:53:03,620 --> 00:53:06,310 So what this does is it protects us against typos. 902 00:53:06,310 --> 00:53:11,410 So say I had accidentally typed this in as Update Users plural, 903 00:53:11,410 --> 00:53:13,510 now it's never going to match. 904 00:53:13,510 --> 00:53:15,880 And it might be difficult when we're trying to debug. 905 00:53:15,880 --> 00:53:17,300 Like, hey, what's going wrong? 906 00:53:17,300 --> 00:53:21,410 I'm passing this action called Update User, and it's not updating our user. 907 00:53:21,410 --> 00:53:21,910 Why? 908 00:53:21,910 --> 00:53:25,710 Because we're actually looking for an action type called Update Users plural. 909 00:53:25,710 --> 00:53:35,110 And so to save us from that, we just create a constant called Update User. 910 00:53:35,110 --> 00:53:40,840 And the way that we enforce that our action types are the same 911 00:53:40,840 --> 00:53:42,820 is by using JavaScript itself. 912 00:53:42,820 --> 00:53:46,010 If we made a typo here called Update Users, what's going to happen? 913 00:53:46,010 --> 00:53:50,800 914 00:53:50,800 --> 00:53:55,640 We get an error, because this constant called Update Users is not defined. 915 00:53:55,640 --> 00:54:04,730 And so by storing our actions as constants, 916 00:54:04,730 --> 00:54:10,270 we can ensure that we don't have any weird bugs due to typos. 917 00:54:10,270 --> 00:54:13,570 So let's actually move this to the top of the file, that way we can use it 918 00:54:13,570 --> 00:54:16,345 in our reducers. 919 00:54:16,345 --> 00:54:18,895 920 00:54:18,895 --> 00:54:20,770 And we'll leave a little comment for ourself, 921 00:54:20,770 --> 00:54:22,186 and let's call these Action Types. 922 00:54:22,186 --> 00:54:25,010 923 00:54:25,010 --> 00:54:25,510 Cool. 924 00:54:25,510 --> 00:54:26,770 So a little bit cleaner now. 925 00:54:26,770 --> 00:54:29,380 We no longer have those hardcoded strings. 926 00:54:29,380 --> 00:54:32,216 But now, every single time we want to dispatch an action, 927 00:54:32,216 --> 00:54:33,840 we have to type that entire action out. 928 00:54:33,840 --> 00:54:37,270 And so maybe it might be better to create a function that 929 00:54:37,270 --> 00:54:39,370 creates our actions for us. 930 00:54:39,370 --> 00:54:45,600 And so let's just create a function called Update User. 931 00:54:45,600 --> 00:54:46,460 And what does it do? 932 00:54:46,460 --> 00:54:47,830 Well, it takes some new user-- 933 00:54:47,830 --> 00:54:50,700 934 00:54:50,700 --> 00:54:52,886 let's just update. 935 00:54:52,886 --> 00:54:55,520 So it takes some sort of update, and what does it do? 936 00:54:55,520 --> 00:54:59,710 Well, it returns a new object, because, as we remember, 937 00:54:59,710 --> 00:55:03,280 actions are just objects of a certain type. 938 00:55:03,280 --> 00:55:05,980 And the reason that we create those is because of the standard 939 00:55:05,980 --> 00:55:08,050 called Flux standard action. 940 00:55:08,050 --> 00:55:11,920 And so each of them have a type key. 941 00:55:11,920 --> 00:55:15,230 And what is the type every time you want to update the user? 942 00:55:15,230 --> 00:55:19,022 Well, it's just going to be Update User. 943 00:55:19,022 --> 00:55:20,230 And what is the payload here? 944 00:55:20,230 --> 00:55:22,870 945 00:55:22,870 --> 00:55:25,567 Well, it depends what we're invoking Update User on. 946 00:55:25,567 --> 00:55:27,150 And so let's just pass the updated in. 947 00:55:27,150 --> 00:55:31,150 948 00:55:31,150 --> 00:55:37,350 So now, rather than typing this whole thing out, we can just do Update User 949 00:55:37,350 --> 00:55:42,810 and pass the update that we want to make. 950 00:55:42,810 --> 00:55:44,090 And what happens here? 951 00:55:44,090 --> 00:55:46,230 Well, Update User up here gets invoked. 952 00:55:46,230 --> 00:55:51,010 We pass the update that we want to make, and it returns an action. 953 00:55:51,010 --> 00:55:53,594 And the action gets passed to dispatch as if we had done this. 954 00:55:53,594 --> 00:55:55,551 It's just a little bit cleaner because we don't 955 00:55:55,551 --> 00:55:57,448 have to type this whole string out. 956 00:55:57,448 --> 00:56:02,230 957 00:56:02,230 --> 00:56:10,360 So now let's do the same thing here, and here. 958 00:56:10,360 --> 00:56:16,030 959 00:56:16,030 --> 00:56:16,530 Cool. 960 00:56:16,530 --> 00:56:19,260 Looking cleaner already. 961 00:56:19,260 --> 00:56:23,700 This also looks a little bit gross, so let's create a creator for that 962 00:56:23,700 --> 00:56:25,260 as well. 963 00:56:25,260 --> 00:56:28,920 And let's call this Add Contact. 964 00:56:28,920 --> 00:56:32,320 And we're going to pass it to newContact. 965 00:56:32,320 --> 00:56:33,570 And how is this going to look? 966 00:56:33,570 --> 00:56:36,300 967 00:56:36,300 --> 00:56:39,150 Well, just like our other action creator, 968 00:56:39,150 --> 00:56:40,820 it's going to return an action. 969 00:56:40,820 --> 00:56:42,069 What does an action look like? 970 00:56:42,069 --> 00:56:43,897 Well, it has a type attribute. 971 00:56:43,897 --> 00:56:44,730 And what type is it? 972 00:56:44,730 --> 00:56:47,167 It's going to be Update Contact. 973 00:56:47,167 --> 00:56:48,750 And it's also going to have a payload. 974 00:56:48,750 --> 00:56:50,515 And what is the payload here? 975 00:56:50,515 --> 00:56:52,140 Well, it's going to be that NewContact. 976 00:56:52,140 --> 00:56:55,590 977 00:56:55,590 --> 00:57:03,541 And so now we can do the same thing by calling Add Contact here and on here as 978 00:57:03,541 --> 00:57:04,040 well. 979 00:57:04,040 --> 00:57:08,981 980 00:57:08,981 --> 00:57:09,480 Cool. 981 00:57:09,480 --> 00:57:12,190 And now it's looking a lot more readable. 982 00:57:12,190 --> 00:57:19,290 So let's just label these as are action creators, because they're 983 00:57:19,290 --> 00:57:21,330 creating actions. 984 00:57:21,330 --> 00:57:22,320 We have our store-- 985 00:57:22,320 --> 00:57:22,890 our reducer. 986 00:57:22,890 --> 00:57:29,460 We have our specific reducers for each key. 987 00:57:29,460 --> 00:57:33,200 And then we pass those to our store, and we go ahead and dispatch foo actions. 988 00:57:33,200 --> 00:57:34,700 And what actions are we dispatching? 989 00:57:34,700 --> 00:57:37,200 Well, it seems a lot easier to read now. 990 00:57:37,200 --> 00:57:41,466 First we say, hey store, go ahead and update the user. 991 00:57:41,466 --> 00:57:42,840 And what are we updating it with? 992 00:57:42,840 --> 00:57:44,475 Well, we're just passing foo foo. 993 00:57:44,475 --> 00:57:46,350 Go ahead and update the user again with this. 994 00:57:46,350 --> 00:57:47,940 Update user again with this. 995 00:57:47,940 --> 00:57:49,740 Now add a contact that looks like this. 996 00:57:49,740 --> 00:57:51,198 Add a contact that looks like this. 997 00:57:51,198 --> 00:57:54,030 And now, all of a sudden, it's very readable. 998 00:57:54,030 --> 00:57:55,510 We create a new store. 999 00:57:55,510 --> 00:57:57,660 We pass it in the reducer in the default state. 1000 00:57:57,660 --> 00:57:59,850 We dispatch a few actions. 1001 00:57:59,850 --> 00:58:02,910 And then we go ahead and get the store, get the state 1002 00:58:02,910 --> 00:58:04,500 and see what it looks like. 1003 00:58:04,500 --> 00:58:06,075 And if I didn't make any typos-- 1004 00:58:06,075 --> 00:58:09,617 1005 00:58:09,617 --> 00:58:12,080 oh, I made some typos. 1006 00:58:12,080 --> 00:58:17,160 I never fixed the typo that I made intentionally, so let's fix that. 1007 00:58:17,160 --> 00:58:23,310 1008 00:58:23,310 --> 00:58:26,560 Now we get back exactly what we wanted. 1009 00:58:26,560 --> 00:58:27,060 Great. 1010 00:58:27,060 --> 00:58:32,800 So now our homemade simpleRedux is looking pretty good. 1011 00:58:32,800 --> 00:58:39,190 We've implemented most of what is core to Redux. 1012 00:58:39,190 --> 00:58:41,530 There is a single source of truth for our data. 1013 00:58:41,530 --> 00:58:43,410 It's in our store. 1014 00:58:43,410 --> 00:58:45,660 The state can only be updated by actions. 1015 00:58:45,660 --> 00:58:55,280 So remember, we're dispatching actions down there, 1016 00:58:55,280 --> 00:58:59,210 and there's really no other way to update. 1017 00:58:59,210 --> 00:59:01,640 And how are we doing the update ourselves? 1018 00:59:01,640 --> 00:59:04,640 Well, it's a pure function that takes the old state, 1019 00:59:04,640 --> 00:59:07,280 and some sort of payload or update-- 1020 00:59:07,280 --> 00:59:08,870 or action, I should say-- 1021 00:59:08,870 --> 00:59:10,870 and then goes ahead and does it. 1022 00:59:10,870 --> 00:59:11,870 Did it do anything else? 1023 00:59:11,870 --> 00:59:12,710 Did it console log? 1024 00:59:12,710 --> 00:59:15,230 Did it change any variables outside its scope? 1025 00:59:15,230 --> 00:59:21,907 Did it use anything outside of the arguments that it was passed? 1026 00:59:21,907 --> 00:59:22,490 No, it didn't. 1027 00:59:22,490 --> 00:59:26,540 It was just a pure function of the old state and the updates. 1028 00:59:26,540 --> 00:59:29,240 And it has this pattern, right? 1029 00:59:29,240 --> 00:59:33,420 We're sending actions that pass through the reducer and it updates our store. 1030 00:59:33,420 --> 00:59:37,760 And so now, we've pretty much implemented a simpleRedux. 1031 00:59:37,760 --> 00:59:41,760 1032 00:59:41,760 --> 00:59:46,905 There's just one scalability problem with our current Redux. 1033 00:59:46,905 --> 00:59:50,790 1034 00:59:50,790 --> 00:59:56,590 So what happens when we want to update a user? 1035 00:59:56,590 --> 01:00:03,000 We also-- or maybe we want to update a contact, and maybe, in our userReducer, 1036 01:00:03,000 --> 01:00:06,600 we want to keep track of the number of contacts in our user metadata. 1037 01:00:06,600 --> 01:00:13,630 We're going to have to change a lot of lines of code in order to do that. 1038 01:00:13,630 --> 01:00:17,460 And so as we start to add more reducers, start to add more things to our state, 1039 01:00:17,460 --> 01:00:23,820 in our current implementation of our reducer, it's non-trivial to do that. 1040 01:00:23,820 --> 01:00:27,060 And so let's actually figure out a better way to do that. 1041 01:00:27,060 --> 01:00:31,200 Right now, what we're doing is our reducer is taking an action, 1042 01:00:31,200 --> 01:00:36,090 consuming it, and sending it to one of the smaller reducers 1043 01:00:36,090 --> 01:00:38,340 that we've created. 1044 01:00:38,340 --> 01:00:40,860 But there's really no reason that we need to do that. 1045 01:00:40,860 --> 01:00:44,940 Maybe a better way would be to take an action 1046 01:00:44,940 --> 01:00:47,580 and pass it to every single reducer. 1047 01:00:47,580 --> 01:00:52,007 That way, it's up to the smaller reducer to decide, hey, 1048 01:00:52,007 --> 01:00:53,340 I want to listen to this action. 1049 01:00:53,340 --> 01:00:57,480 Or maybe I'm just going to ignore this action and return my type. 1050 01:00:57,480 --> 01:00:59,110 So again, why are we doing that? 1051 01:00:59,110 --> 01:01:01,290 It's because we run into scalability issues 1052 01:01:01,290 --> 01:01:06,660 if we want multiple actions, or multiple of these smaller reducers, 1053 01:01:06,660 --> 01:01:10,950 to react to multiple of the types. 1054 01:01:10,950 --> 01:01:14,370 So what exactly would that look like? 1055 01:01:14,370 --> 01:01:21,110 So now, rather than our main reducer here deciding which of these reducers 1056 01:01:21,110 --> 01:01:26,430 to pass to, we should just pass the action to all of them. 1057 01:01:26,430 --> 01:01:32,210 And so let's actually redefine our reducer down here. 1058 01:01:32,210 --> 01:01:35,370 1059 01:01:35,370 --> 01:01:38,900 So right now, our reducer is taking a state in action. 1060 01:01:38,900 --> 01:01:46,490 And maybe what it should be doing is passing back 1061 01:01:46,490 --> 01:01:53,951 a function where we know we want users, our user, 1062 01:01:53,951 --> 01:01:55,325 and we know we want our contacts. 1063 01:01:55,325 --> 01:02:00,340 1064 01:02:00,340 --> 01:02:02,530 And what is responsible for keeping track 1065 01:02:02,530 --> 01:02:06,820 of our user part of our global state? 1066 01:02:06,820 --> 01:02:09,590 Well, it's the reducer that's specific to the user. 1067 01:02:09,590 --> 01:02:14,320 And so maybe here we want to invoke the userReducer with some values. 1068 01:02:14,320 --> 01:02:20,090 And maybe here, we want to invoke the contacts reducer with some value. 1069 01:02:20,090 --> 01:02:22,570 So now it's starting to look a lot simpler. 1070 01:02:22,570 --> 01:02:27,960 And what values does the userReducer care about? 1071 01:02:27,960 --> 01:02:33,420 Well, just the part of the state that it cares about, so the state, dot, user. 1072 01:02:33,420 --> 01:02:36,460 And same thing with the contactReducer. 1073 01:02:36,460 --> 01:02:45,426 We only care about the part of state that's useful to the contactReducer. 1074 01:02:45,426 --> 01:02:47,050 And how does it know what it should do? 1075 01:02:47,050 --> 01:02:48,383 Well, we just passed the action. 1076 01:02:48,383 --> 01:02:52,080 1077 01:02:52,080 --> 01:02:55,060 So that there is our new reducer. 1078 01:02:55,060 --> 01:03:01,690 And so let's now modify our userReducer and contactReducer 1079 01:03:01,690 --> 01:03:07,086 to only respond to the action types that they care about. 1080 01:03:07,086 --> 01:03:13,246 So let's get rid of this, because now we need additional logic here, 1081 01:03:13,246 --> 01:03:15,020 and maybe some additional logic here. 1082 01:03:15,020 --> 01:03:21,430 1083 01:03:21,430 --> 01:03:24,810 So currently, what cares about Update User? 1084 01:03:24,810 --> 01:03:27,870 Well, it's just the userReducer. 1085 01:03:27,870 --> 01:03:32,630 So if the action type is Update User in the userReducer, 1086 01:03:32,630 --> 01:03:36,900 let's go ahead and return that update. 1087 01:03:36,900 --> 01:03:42,640 Otherwise, let's just return the state as it was before. 1088 01:03:42,640 --> 01:03:45,450 And now we can get rid of all of that logic here. 1089 01:03:45,450 --> 01:03:50,520 And now let's do a similar thing with the logic for contactReducer. 1090 01:03:50,520 --> 01:03:55,020 So if the action type is Update Contact, the contactReducer cares about that. 1091 01:03:55,020 --> 01:03:58,020 And we should return just this. 1092 01:03:58,020 --> 01:04:03,915 1093 01:04:03,915 --> 01:04:07,275 Else we'll return the basic state. 1094 01:04:07,275 --> 01:04:09,900 So let me just finish deleting all the code that we don't need. 1095 01:04:09,900 --> 01:04:12,670 1096 01:04:12,670 --> 01:04:13,170 All right. 1097 01:04:13,170 --> 01:04:13,790 Almost there. 1098 01:04:13,790 --> 01:04:15,900 There are still a couple of bugs. 1099 01:04:15,900 --> 01:04:22,140 So for the conductReducer, what is action? 1100 01:04:22,140 --> 01:04:24,360 Action, dot, type doesn't exist currently, 1101 01:04:24,360 --> 01:04:27,630 so we're no longer passing it the newContact. 1102 01:04:27,630 --> 01:04:29,740 Now, we're passing it the action. 1103 01:04:29,740 --> 01:04:32,670 And so we check the action, dot, type. 1104 01:04:32,670 --> 01:04:34,740 And newContact no longer exists. 1105 01:04:34,740 --> 01:04:36,420 Where are we storing the newContact? 1106 01:04:36,420 --> 01:04:37,961 Well, it's just action, dot, payload. 1107 01:04:37,961 --> 01:04:41,001 1108 01:04:41,001 --> 01:04:42,250 And we do the same thing here. 1109 01:04:42,250 --> 01:04:43,916 We're no longer just passing the update. 1110 01:04:43,916 --> 01:04:48,580 We're passing the whole action, and then we can do action, dot, payload. 1111 01:04:48,580 --> 01:04:51,510 1112 01:04:51,510 --> 01:04:53,840 And now we're done. 1113 01:04:53,840 --> 01:04:56,207 So we can make this a little bit more concise, 1114 01:04:56,207 --> 01:04:57,540 if it's easier to read this way. 1115 01:04:57,540 --> 01:05:01,900 1116 01:05:01,900 --> 01:05:03,550 And now it all fits on one page. 1117 01:05:03,550 --> 01:05:08,180 So we have our contactReducer, which cares about the state. 1118 01:05:08,180 --> 01:05:12,160 And when we say state, it's local only to the contacts part of the state. 1119 01:05:12,160 --> 01:05:14,230 It received actions. 1120 01:05:14,230 --> 01:05:16,360 And if the action is that it should update 1121 01:05:16,360 --> 01:05:18,580 the contact, returning a new state. 1122 01:05:18,580 --> 01:05:20,470 And what is the new state? 1123 01:05:20,470 --> 01:05:24,310 Well, it's the old state, and we append to the end whatever the payload is. 1124 01:05:24,310 --> 01:05:29,110 And in this case, the action, dot, payload is the new user. 1125 01:05:29,110 --> 01:05:32,170 Does contactReducer care about Update User? 1126 01:05:32,170 --> 01:05:32,830 No, it doesn't. 1127 01:05:32,830 --> 01:05:36,250 1128 01:05:36,250 --> 01:05:39,810 So if the action, dot, type is an Update Contact, 1129 01:05:39,810 --> 01:05:43,360 we just return whatever the state was before, no big deal. 1130 01:05:43,360 --> 01:05:45,390 And the same thing is true for userReducer. 1131 01:05:45,390 --> 01:05:46,881 It's taking a state. 1132 01:05:46,881 --> 01:05:48,130 What state does it care about? 1133 01:05:48,130 --> 01:05:51,610 Well, it's only the user part of our application state. 1134 01:05:51,610 --> 01:05:54,756 It takes an action as well. 1135 01:05:54,756 --> 01:05:57,130 And if the action type is that it should update the user, 1136 01:05:57,130 --> 01:05:58,504 then it goes ahead and does that. 1137 01:05:58,504 --> 01:06:00,670 It returns the old state. 1138 01:06:00,670 --> 01:06:04,450 And into that, we merge the new action, dot, payload. 1139 01:06:04,450 --> 01:06:07,420 And if the action type is in Update User, 1140 01:06:07,420 --> 01:06:11,260 just return whatever the user information was before. 1141 01:06:11,260 --> 01:06:14,740 And one key difference here is that for every single action, 1142 01:06:14,740 --> 01:06:17,030 every single one of these reducers is called. 1143 01:06:17,030 --> 01:06:21,490 This reducer is called and passes that action along with the subset of state 1144 01:06:21,490 --> 01:06:25,450 that each one of these reducers cares about to them. 1145 01:06:25,450 --> 01:06:28,810 And then these reducers only do something 1146 01:06:28,810 --> 01:06:30,970 if the type is something that they care about. 1147 01:06:30,970 --> 01:06:33,844 Otherwise, they just return the state blindly as it was. 1148 01:06:33,844 --> 01:06:37,960 1149 01:06:37,960 --> 01:06:42,980 So now everything is a lot more concise. 1150 01:06:42,980 --> 01:06:47,990 And now if we wanted to respond to changes 1151 01:06:47,990 --> 01:06:50,400 in other types in the userReducer, we can. 1152 01:06:50,400 --> 01:06:57,080 So if we wanted to store something in the user part of the state 1153 01:06:57,080 --> 01:07:02,850 every single time we add a contact, we can do that now. 1154 01:07:02,850 --> 01:07:08,200 So maybe if we add a new user, or a NewContact-- 1155 01:07:08,200 --> 01:07:13,670 maybe want to store that most recently added contact in the user information-- 1156 01:07:13,670 --> 01:07:16,952 we could do that by doing state. 1157 01:07:16,952 --> 01:07:18,410 And what are we merging into state? 1158 01:07:18,410 --> 01:07:29,840 Well, let's just do recently added or prevContact 1159 01:07:29,840 --> 01:07:32,450 is whatever that contact is, so action, dot, payload. 1160 01:07:32,450 --> 01:07:36,810 1161 01:07:36,810 --> 01:07:46,900 And now when we add new contacts, the previous contact is saved in the user. 1162 01:07:46,900 --> 01:07:50,475 And so now, every single reducer can respond to every single action. 1163 01:07:50,475 --> 01:07:53,870 1164 01:07:53,870 --> 01:08:02,530 And let's just make sure it works by adding 1165 01:08:02,530 --> 01:08:21,920 the contact that wasn't the same as before, as soon 1166 01:08:21,920 --> 01:08:23,420 as my computer unfreezes. 1167 01:08:23,420 --> 01:08:28,304 1168 01:08:28,304 --> 01:08:28,970 Let's just kill. 1169 01:08:28,970 --> 01:08:46,750 1170 01:08:46,750 --> 01:08:56,470 So let's, again, go into our simpleRedux and ensure that we 1171 01:08:56,470 --> 01:08:58,330 don't pass the same user in again. 1172 01:08:58,330 --> 01:09:02,210 So we can just sanity check to make sure you're saving the most recent user. 1173 01:09:02,210 --> 01:09:04,220 We can add David here. 1174 01:09:04,220 --> 01:09:13,260 1175 01:09:13,260 --> 01:09:17,010 And now we can confirm that the previous contacts stored in the user 1176 01:09:17,010 --> 01:09:21,460 is indeed the most recently-added contact. 1177 01:09:21,460 --> 01:09:27,840 And so now we have pretty much a full implementation of Redux. 1178 01:09:27,840 --> 01:09:32,270 So it's a data-management utility that we've created. 1179 01:09:32,270 --> 01:09:34,520 There is a single source of truth for all of our data. 1180 01:09:34,520 --> 01:09:36,330 It's stored in our store. 1181 01:09:36,330 --> 01:09:39,390 The state can only be updated by our actions. 1182 01:09:39,390 --> 01:09:43,560 And updates are made using our peer functions or our reducers. 1183 01:09:43,560 --> 01:09:47,020 And we've created a reducer. 1184 01:09:47,020 --> 01:09:49,229 We've created a store that maintains the state. 1185 01:09:49,229 --> 01:09:52,109 We can get the state using getState. 1186 01:09:52,109 --> 01:09:53,400 And we've created some actions. 1187 01:09:53,400 --> 01:09:56,022 1188 01:09:56,022 --> 01:09:57,730 So let's go ahead and take a short break. 1189 01:09:57,730 --> 01:10:02,000 And then when we come back, we can add Redux to our actual application. 1190 01:10:02,000 --> 01:10:03,920 All right, hello and welcome back. 1191 01:10:03,920 --> 01:10:08,440 Before the break, we actually implemented our own small simpleRedux. 1192 01:10:08,440 --> 01:10:12,700 And now, let's actually start moving from our simpleRedux, 1193 01:10:12,700 --> 01:10:15,920 to the actual Redux implementation. 1194 01:10:15,920 --> 01:10:19,960 Our Redux implementation already has a pretty similar API. 1195 01:10:19,960 --> 01:10:23,050 What we're missing is just a way to notify that the state is updated. 1196 01:10:23,050 --> 01:10:27,010 And so let's actually install Redux and start to convert 1197 01:10:27,010 --> 01:10:30,850 what we have into actual Redux. 1198 01:10:30,850 --> 01:10:39,760 So one good place to start would be to NPM install Redux. 1199 01:10:39,760 --> 01:10:42,100 And so, as we talked about in previous lectures, 1200 01:10:42,100 --> 01:10:45,880 NPM install will install some NPM package 1201 01:10:45,880 --> 01:10:49,060 and add it automatically to our package, dot, json file. 1202 01:10:49,060 --> 01:10:53,860 And so if we now look at our package, dot, json, 1203 01:10:53,860 --> 01:10:56,650 we see that Redux has been added down here. 1204 01:10:56,650 --> 01:10:59,260 1205 01:10:59,260 --> 01:11:04,765 So let's now go ahead and start moving what we have into actual Redux. 1206 01:11:04,765 --> 01:11:22,740 1207 01:11:22,740 --> 01:11:27,570 So I just copied exactly what we had from our simple implementation 1208 01:11:27,570 --> 01:11:30,570 into this new directory called Redux. 1209 01:11:30,570 --> 01:11:35,470 And here, we're going to start actually using Redux. 1210 01:11:35,470 --> 01:11:42,150 And so first thing we need to do is add this thing called createReducer, 1211 01:11:42,150 --> 01:11:43,660 or createStore rather. 1212 01:11:43,660 --> 01:11:50,450 So if we import createStore from Redux, now we 1213 01:11:50,450 --> 01:11:54,950 have Redux's implementation of a store. 1214 01:11:54,950 --> 01:11:58,760 And so previously we had our class store, 1215 01:11:58,760 --> 01:12:02,360 which took a reducer, and maybe some initial state, 1216 01:12:02,360 --> 01:12:06,800 and implemented all of the things that we thought we needed ourselves. 1217 01:12:06,800 --> 01:12:09,800 But now, we're actually going to use this function called createStore 1218 01:12:09,800 --> 01:12:10,790 from Redux. 1219 01:12:10,790 --> 01:12:16,700 And so now, we can actually just delete that implementation ourselves. 1220 01:12:16,700 --> 01:12:23,060 And so now when we do new store down here, now instead of doing new store, 1221 01:12:23,060 --> 01:12:26,480 we'll just invoke that thing called createStore from Redux. 1222 01:12:26,480 --> 01:12:29,020 1223 01:12:29,020 --> 01:12:31,400 And since I read that documentation, I know that it 1224 01:12:31,400 --> 01:12:34,950 takes a reducer and some default state. 1225 01:12:34,950 --> 01:12:37,580 And then we can dispatch some actions. 1226 01:12:37,580 --> 01:12:44,040 And other than that, I think that's it. 1227 01:12:44,040 --> 01:12:48,110 So that one line change there actually took us 1228 01:12:48,110 --> 01:12:54,680 from our simple implementation of Redux to actual implementation of Redux. 1229 01:12:54,680 --> 01:12:57,410 Unfortunately, if we want to run this in node, 1230 01:12:57,410 --> 01:12:59,610 it doesn't support that import statement. 1231 01:12:59,610 --> 01:13:09,620 So I'm just going to do this real quick, which does effectively the same thing, 1232 01:13:09,620 --> 01:13:10,790 just so that we can test it. 1233 01:13:10,790 --> 01:13:13,560 1234 01:13:13,560 --> 01:13:15,990 So let's run this. 1235 01:13:15,990 --> 01:13:17,100 And what do you know? 1236 01:13:17,100 --> 01:13:20,670 We got back exactly what we had before. 1237 01:13:20,670 --> 01:13:23,030 So it turns out the simple implementation of Redux 1238 01:13:23,030 --> 01:13:28,790 that we actually wrote pretty much adheres to the same API 1239 01:13:28,790 --> 01:13:31,700 that Redux itself has. 1240 01:13:31,700 --> 01:13:37,160 And so it didn't really take much for us to move from our simple implementation 1241 01:13:37,160 --> 01:13:40,500 to actual Redux. 1242 01:13:40,500 --> 01:13:43,145 Redux actually, also, gives us a few other goodies. 1243 01:13:43,145 --> 01:13:45,890 1244 01:13:45,890 --> 01:13:52,810 So right now, the way that we create a reducer that dispatches 1245 01:13:52,810 --> 01:13:57,920 or that passes actions on to their relevant reducers 1246 01:13:57,920 --> 01:14:01,470 is by combining them using a function that we defined here. 1247 01:14:01,470 --> 01:14:11,120 But it turns out Redux also gives us a function called combineReducer, which 1248 01:14:11,120 --> 01:14:14,120 does effectively the same thing for us. 1249 01:14:14,120 --> 01:14:17,770 Rather than us writing a function that combines the reducers, 1250 01:14:17,770 --> 01:14:23,600 we can actually invoke this thing called createReducer, 1251 01:14:23,600 --> 01:14:27,260 or combineReducers from Redux. 1252 01:14:27,260 --> 01:14:31,940 That just takes an object that maps the key in the actual store 1253 01:14:31,940 --> 01:14:34,490 with the reducer that controls that key. 1254 01:14:34,490 --> 01:14:43,250 And so it can do user gets userReducer and contacts gets contactReducer. 1255 01:14:43,250 --> 01:14:45,920 1256 01:14:45,920 --> 01:14:49,340 And now, we've basically taken a little bit more complexity 1257 01:14:49,340 --> 01:14:54,900 out of our application and maintain the same functionality. 1258 01:14:54,900 --> 01:15:04,550 So again, if we test this, we don't have the initial state. 1259 01:15:04,550 --> 01:15:07,290 1260 01:15:07,290 --> 01:15:11,980 So one difference here is that-- 1261 01:15:11,980 --> 01:15:13,865 did we not pass the initial state in? 1262 01:15:13,865 --> 01:15:18,990 1263 01:15:18,990 --> 01:15:24,362 Let's actually-- just to safeguard real quick, that if this is null, or empty, 1264 01:15:24,362 --> 01:15:26,070 we'll go ahead and just create in Default 1265 01:15:26,070 --> 01:15:29,070 State for each individual reducer. 1266 01:15:29,070 --> 01:15:32,820 So for the user, let's have an empty object. 1267 01:15:32,820 --> 01:15:40,620 And for the contacts, let's have an empty array like that, and now run it. 1268 01:15:40,620 --> 01:15:44,340 Now we get back exactly what we had before, as expected. 1269 01:15:44,340 --> 01:15:51,030 The one minor difference is that rather than having a default state app-wide, 1270 01:15:51,030 --> 01:15:55,930 we can actually just define the Default State in the reducers themselves. 1271 01:15:55,930 --> 01:15:59,670 And so the Default State for the contacts in our contactReducer 1272 01:15:59,670 --> 01:16:01,590 is just an empty array. 1273 01:16:01,590 --> 01:16:05,130 And the Default State for our user, if the userReducer 1274 01:16:05,130 --> 01:16:09,660 is invoked with no current state, we'll go ahead and initialize it 1275 01:16:09,660 --> 01:16:12,400 to some empty object. 1276 01:16:12,400 --> 01:16:15,930 And so now, I see even more complexity gone 1277 01:16:15,930 --> 01:16:18,750 that just goes into the Redux library, rather than 1278 01:16:18,750 --> 01:16:23,020 our own implementation in this file. 1279 01:16:23,020 --> 01:16:23,520 Great. 1280 01:16:23,520 --> 01:16:29,070 So now we have a working store. 1281 01:16:29,070 --> 01:16:32,850 It's just a lot of stuff in a single file. 1282 01:16:32,850 --> 01:16:35,160 There's no reason that our store, dot, js 1283 01:16:35,160 --> 01:16:40,860 file should have our store, but also our action creators, 1284 01:16:40,860 --> 01:16:44,690 also our reducers, and also all of our actions. 1285 01:16:44,690 --> 01:16:47,100 And so let's start to split those out into separate files 1286 01:16:47,100 --> 01:16:50,870 so that they're easier to maintain and find. 1287 01:16:50,870 --> 01:17:01,900 So let's copy the store in to read this thing called reducer, dot, js-- 1288 01:17:01,900 --> 01:17:04,730 and also copy the store into this thing called actions, dot, js. 1289 01:17:04,730 --> 01:17:08,310 1290 01:17:08,310 --> 01:17:12,000 So in reducer-- actually, let's do actions first. 1291 01:17:12,000 --> 01:17:19,570 In actions, what do we care about in actions? 1292 01:17:19,570 --> 01:17:24,730 We really only care about our action types and our action creators. 1293 01:17:24,730 --> 01:17:27,200 CombineReducers, those things about stores, 1294 01:17:27,200 --> 01:17:30,460 we really don't care about at all, so we can just delete that. 1295 01:17:30,460 --> 01:17:32,360 We don't care about that. 1296 01:17:32,360 --> 01:17:35,470 We don't care about any of these reducers. 1297 01:17:35,470 --> 01:17:39,290 But we do, however, care about the action creators. 1298 01:17:39,290 --> 01:17:41,980 So now, in our file called actions, dot, js, 1299 01:17:41,980 --> 01:17:44,510 we define the things that have to do with our actions. 1300 01:17:44,510 --> 01:17:48,490 So there are our action types and our action creators. 1301 01:17:48,490 --> 01:17:52,840 Some people prefer to have action types and action creators in separate files. 1302 01:17:52,840 --> 01:17:54,820 But since we only have two of each, let's just 1303 01:17:54,820 --> 01:17:58,162 keep them in these files called actions, dot, js for now. 1304 01:17:58,162 --> 01:17:59,620 And let's go ahead and export them. 1305 01:17:59,620 --> 01:18:07,460 1306 01:18:07,460 --> 01:18:10,480 So now in our actions, dot, js file, we are just 1307 01:18:10,480 --> 01:18:13,370 exporting the available action types. 1308 01:18:13,370 --> 01:18:16,880 And we're also exporting the available action creators. 1309 01:18:16,880 --> 01:18:21,010 And that's all that this file called actions cares about. 1310 01:18:21,010 --> 01:18:23,270 Now let's move on to reducer. 1311 01:18:23,270 --> 01:18:28,160 So does the reducer care about combineReducers and createStore? 1312 01:18:28,160 --> 01:18:32,690 Well, half of it, it cares about combineReducers but not createStore. 1313 01:18:32,690 --> 01:18:37,365 And let's actually move back to our ES6 import, syntax. 1314 01:18:37,365 --> 01:18:40,270 1315 01:18:40,270 --> 01:18:43,160 Do we care about action types? 1316 01:18:43,160 --> 01:18:48,247 Yes, we do, because the reducer is checking against action types. 1317 01:18:48,247 --> 01:18:50,830 But there's no reason that we should define them in this file. 1318 01:18:50,830 --> 01:18:54,375 We should actually just import them from our file called actions. 1319 01:18:54,375 --> 01:19:04,870 1320 01:19:04,870 --> 01:19:08,440 And now we can go ahead and delete the lines here. 1321 01:19:08,440 --> 01:19:16,130 1322 01:19:16,130 --> 01:19:19,630 And so now, what we have in this file is basically only the things 1323 01:19:19,630 --> 01:19:22,390 that we need to define our reducers. 1324 01:19:22,390 --> 01:19:24,820 And so we need this helper function called merge, 1325 01:19:24,820 --> 01:19:28,300 which takes a couple of objects and merges them together. 1326 01:19:28,300 --> 01:19:33,610 We define our Default State here, though we don't really need to. 1327 01:19:33,610 --> 01:19:38,810 And then we have two separate reducers for two parts of our application. 1328 01:19:38,810 --> 01:19:42,760 So for the part of our application that cares about contacts, 1329 01:19:42,760 --> 01:19:45,190 we have this reducer, which takes state, which 1330 01:19:45,190 --> 01:19:48,940 is initialized to an empty array-- so just an empty list of contacts. 1331 01:19:48,940 --> 01:19:54,260 We take an action, and we match against the action to see what we should do. 1332 01:19:54,260 --> 01:19:58,790 We have the reducer for users here. 1333 01:19:58,790 --> 01:20:03,100 So we say, give me a starting state for our users. 1334 01:20:03,100 --> 01:20:07,500 If there's no previous state, just initialize it to an empty object. 1335 01:20:07,500 --> 01:20:10,750 And give me an action, and we'll go ahead and match against the action type 1336 01:20:10,750 --> 01:20:12,470 to see what we should do. 1337 01:20:12,470 --> 01:20:15,010 And then we have our actual reducer that we're 1338 01:20:15,010 --> 01:20:20,030 going to pass to our store, which just combines those two reducers. 1339 01:20:20,030 --> 01:20:24,250 So just to stay maintainable and scalable, what we're doing 1340 01:20:24,250 --> 01:20:28,150 is rather than having one reducer check against all action types 1341 01:20:28,150 --> 01:20:31,960 and maintain the entire state, we have separate reducers 1342 01:20:31,960 --> 01:20:35,260 for the part of the state that cares about user and the part 1343 01:20:35,260 --> 01:20:37,210 of the state that cares about contacts. 1344 01:20:37,210 --> 01:20:39,280 And if we want to scale up to the point where 1345 01:20:39,280 --> 01:20:43,780 our user is starting to be an object that 1346 01:20:43,780 --> 01:20:46,540 is unmaintainable by a single reducer, what we can do 1347 01:20:46,540 --> 01:20:49,922 is we can create one reducer for half of that user, 1348 01:20:49,922 --> 01:20:52,630 and maybe another user for another half, or maybe a third reducer 1349 01:20:52,630 --> 01:20:53,980 for a third key in there-- 1350 01:20:53,980 --> 01:20:59,650 and go ahead and do something here, where it's, like, combine reducers. 1351 01:20:59,650 --> 01:21:06,430 And maybe we have something that cares about the user's meta 1352 01:21:06,430 --> 01:21:11,030 data that's called userMetaReducer. 1353 01:21:11,030 --> 01:21:18,300 And maybe we have something that cares about the user's logins. 1354 01:21:18,300 --> 01:21:20,470 And so every time they have a login, we'll 1355 01:21:20,470 --> 01:21:23,650 go ahead and add that to this part of the user's state. 1356 01:21:23,650 --> 01:21:28,180 And so maybe that is the userLoginReducer. 1357 01:21:28,180 --> 01:21:30,860 And I'm just making up examples that are somewhat arbitrary. 1358 01:21:30,860 --> 01:21:34,800 But I'm just trying to show that as our application scales up, 1359 01:21:34,800 --> 01:21:38,920 and as our application state gets larger and larger, what we can do 1360 01:21:38,920 --> 01:21:43,870 is we can still take bite-sized pieces of that state 1361 01:21:43,870 --> 01:21:46,210 and manage them by one small reducer. 1362 01:21:46,210 --> 01:21:50,950 And we can compose these reducers into just one massive reducer 1363 01:21:50,950 --> 01:21:53,600 that can take care of the entire state. 1364 01:21:53,600 --> 01:21:55,810 And so this combineReducer, what it does is 1365 01:21:55,810 --> 01:22:01,840 it allows us to split up one object into a bunch of separate object keys 1366 01:22:01,840 --> 01:22:06,497 that are maintained by a separate reducer. 1367 01:22:06,497 --> 01:22:08,830 And so since our application is pretty simple right now, 1368 01:22:08,830 --> 01:22:09,960 we can do that all in one. 1369 01:22:09,960 --> 01:22:13,570 But if we wanted to scale up, it is possible to start nesting reducers 1370 01:22:13,570 --> 01:22:16,050 like that. 1371 01:22:16,050 --> 01:22:17,470 Great. 1372 01:22:17,470 --> 01:22:25,540 So let's actually export default, this reducer, 1373 01:22:25,540 --> 01:22:29,440 because that's the only thing that we want to expose from this file. 1374 01:22:29,440 --> 01:22:33,970 We don't ever want somebody to use contactReducer or userReducer alone. 1375 01:22:33,970 --> 01:22:38,230 We just want them to interface with that through this big reducer 1376 01:22:38,230 --> 01:22:40,940 that we have at the end. 1377 01:22:40,940 --> 01:22:43,750 And if it's easier for you to follow like this, 1378 01:22:43,750 --> 01:22:48,670 we can define this variable called reducer and export default 1379 01:22:48,670 --> 01:22:52,090 at the end, which is exactly the same as what we did before. 1380 01:22:52,090 --> 01:22:55,780 But now, we have a handy variable name to let us know 1381 01:22:55,780 --> 01:22:59,670 exactly what this combineReducer is. 1382 01:22:59,670 --> 01:23:00,170 Great. 1383 01:23:00,170 --> 01:23:01,086 So that's the reducer. 1384 01:23:01,086 --> 01:23:03,370 1385 01:23:03,370 --> 01:23:08,720 And now, lastly, let's clean out this store file. 1386 01:23:08,720 --> 01:23:14,470 So we no longer care about that combineReducer function. 1387 01:23:14,470 --> 01:23:17,350 Now we only care about createStore. 1388 01:23:17,350 --> 01:23:21,550 Do we care about action types in our store file? 1389 01:23:21,550 --> 01:23:22,780 No, we don't. 1390 01:23:22,780 --> 01:23:23,860 So let me delete that. 1391 01:23:23,860 --> 01:23:25,989 Do we care about merge and those two reducers? 1392 01:23:25,989 --> 01:23:26,530 No, we don't. 1393 01:23:26,530 --> 01:23:27,760 We can delete that. 1394 01:23:27,760 --> 01:23:29,650 Do we care about our main reducer? 1395 01:23:29,650 --> 01:23:31,760 Yes, we do, but not in the context of this file. 1396 01:23:31,760 --> 01:23:33,850 We can just import it from our other file. 1397 01:23:33,850 --> 01:23:36,550 And so rather than implementing it here, we 1398 01:23:36,550 --> 01:23:43,576 can just import reducer from that file and delete the declaration here. 1399 01:23:43,576 --> 01:23:44,950 Do we care about action creators? 1400 01:23:44,950 --> 01:23:46,010 Not in this file. 1401 01:23:46,010 --> 01:23:49,392 1402 01:23:49,392 --> 01:23:50,350 Do we care about store? 1403 01:23:50,350 --> 01:23:50,980 Yes, we do. 1404 01:23:50,980 --> 01:23:54,820 So let's have const store be this thing that 1405 01:23:54,820 --> 01:23:57,610 creates the store from the reducer. 1406 01:23:57,610 --> 01:23:59,470 And we don't really need the Default State 1407 01:23:59,470 --> 01:24:05,530 since we declared it in each one of the reducers themselves. 1408 01:24:05,530 --> 01:24:12,340 So the Default State is basically this, where an empty contacts key just 1409 01:24:12,340 --> 01:24:13,690 becomes an empty array. 1410 01:24:13,690 --> 01:24:16,210 And an empty user becomes an empty object. 1411 01:24:16,210 --> 01:24:19,480 1412 01:24:19,480 --> 01:24:22,840 And so we're still dispatching a bunch of actions. 1413 01:24:22,840 --> 01:24:33,280 Let's comment those out for now and export this store. 1414 01:24:33,280 --> 01:24:36,681 1415 01:24:36,681 --> 01:24:37,180 Great. 1416 01:24:37,180 --> 01:24:39,400 So now, everything is in its own separate file. 1417 01:24:39,400 --> 01:24:40,840 Everything is very readable. 1418 01:24:40,840 --> 01:24:46,080 I believe every single file can basically be read without scrolling. 1419 01:24:46,080 --> 01:24:47,100 Oh, I lied. 1420 01:24:47,100 --> 01:24:50,410 But very close to that, which is pretty impressive since we're 1421 01:24:50,410 --> 01:24:53,000 only showing fewer than 20 lines at a time. 1422 01:24:53,000 --> 01:24:56,200 So it's very easy to now navigate through our application 1423 01:24:56,200 --> 01:25:00,522 and know exactly where we need to update something if we need to do so. 1424 01:25:00,522 --> 01:25:03,230 So if we need to add a new action, where are we going to do that? 1425 01:25:03,230 --> 01:25:07,570 Well, in our actions file, we can add any action types up here 1426 01:25:07,570 --> 01:25:09,880 and any action creators down here. 1427 01:25:09,880 --> 01:25:15,430 If we want to change any logic in our reducer, we know exactly where that is. 1428 01:25:15,430 --> 01:25:16,720 It's right here. 1429 01:25:16,720 --> 01:25:21,820 If we want to change how we handle contacts, we can do that here. 1430 01:25:21,820 --> 01:25:25,110 If we want to do so with four users, we can do that here. 1431 01:25:25,110 --> 01:25:28,224 And I immediately see a way that we can make this more readable. 1432 01:25:28,224 --> 01:25:30,640 Right now, what we're doing is we're doing if action, dot, 1433 01:25:30,640 --> 01:25:33,190 type is Update User, do this. 1434 01:25:33,190 --> 01:25:34,840 If action, dot, type is this, do this. 1435 01:25:34,840 --> 01:25:36,510 If action, dot, type is this, do this. 1436 01:25:36,510 --> 01:25:39,640 So we keep matching against this string called action, dot, type. 1437 01:25:39,640 --> 01:25:42,160 There's actually something built into JavaScript 1438 01:25:42,160 --> 01:25:47,660 that allows us to more easily match against a single string. 1439 01:25:47,660 --> 01:25:49,100 And that's the switch statement. 1440 01:25:49,100 --> 01:25:54,910 So we could do switch based on action, dot, type here. 1441 01:25:54,910 --> 01:25:57,490 And if you're new to the syntax, basically what it does 1442 01:25:57,490 --> 01:26:02,440 is it allows us to check a particular variable 1443 01:26:02,440 --> 01:26:04,960 and match it against a bunch of different possible values. 1444 01:26:04,960 --> 01:26:06,970 And so if the action, dot, type-- 1445 01:26:06,970 --> 01:26:12,310 it's the case where it's Update User, then we're going to do something. 1446 01:26:12,310 --> 01:26:15,830 And that something is to do this. 1447 01:26:15,830 --> 01:26:20,110 1448 01:26:20,110 --> 01:26:27,485 If it's Update Contact, instead we're going to do this. 1449 01:26:27,485 --> 01:26:30,530 1450 01:26:30,530 --> 01:26:33,080 Otherwise, just return the old state. 1451 01:26:33,080 --> 01:26:37,540 1452 01:26:37,540 --> 01:26:39,530 And now it's a lot easier to read. 1453 01:26:39,530 --> 01:26:41,660 So there is no longer a bunch of if-statements. 1454 01:26:41,660 --> 01:26:45,790 We just know that what we care about is action, dot, type. 1455 01:26:45,790 --> 01:26:50,350 And if the case is a Update User, then we return this. 1456 01:26:50,350 --> 01:26:53,519 If the case is Update Contact, we return this. 1457 01:26:53,519 --> 01:26:55,810 And if it doesn't match any of those things, by default 1458 01:26:55,810 --> 01:26:59,230 we should just return to the original state. 1459 01:26:59,230 --> 01:27:03,490 And then again, we combine the reducers and export it at the end. 1460 01:27:03,490 --> 01:27:08,530 And then we import it into our file in store, dot, js, 1461 01:27:08,530 --> 01:27:13,715 which just creates a store out of that reducer and exports it. 1462 01:27:13,715 --> 01:27:16,090 So again, we didn't really change any of the logic there. 1463 01:27:16,090 --> 01:27:19,580 We just split things into smaller, bite-sized pieces. 1464 01:27:19,580 --> 01:27:22,660 And so a lot of a recurring theme that we see in this class 1465 01:27:22,660 --> 01:27:25,960 is take a big problem and split it into smaller pieces that are 1466 01:27:25,960 --> 01:27:28,880 bite-size and maybe easier to digest. 1467 01:27:28,880 --> 01:27:32,170 So we went ahead and did that with our store here. 1468 01:27:32,170 --> 01:27:39,640 And so now, let's talk about it in the context of React. 1469 01:27:39,640 --> 01:27:42,190 So far, we've only really talked about Redux 1470 01:27:42,190 --> 01:27:46,780 as a standalone library that tracks some data. 1471 01:27:46,780 --> 01:27:52,270 But what we really care about is having that data update some views. 1472 01:27:52,270 --> 01:27:56,980 And so we want to respond to, or React to rather, 1473 01:27:56,980 --> 01:28:00,680 changes in data in our application or UI. 1474 01:28:00,680 --> 01:28:03,880 And so now we have a few questions to answer. 1475 01:28:03,880 --> 01:28:08,320 How do we get the info from our store into our components? 1476 01:28:08,320 --> 01:28:12,400 Because right now, we've been using our store as just a standalone module 1477 01:28:12,400 --> 01:28:16,010 and accessing effectively the command line. 1478 01:28:16,010 --> 01:28:20,080 But now, how do you get this to run in an application? 1479 01:28:20,080 --> 01:28:25,780 Well, it turns out our store has a handy method for getting the info. 1480 01:28:25,780 --> 01:28:27,940 It's called store, dot, getState. 1481 01:28:27,940 --> 01:28:30,100 And so in our application, what we can do 1482 01:28:30,100 --> 01:28:33,650 is we can actually access our state from our store directly. 1483 01:28:33,650 --> 01:28:36,920 So we can do store, dot, getState to receive that. 1484 01:28:36,920 --> 01:28:42,100 And so now let's start integrating Redux into our application. 1485 01:28:42,100 --> 01:28:44,200 So we already have this thing called store. 1486 01:28:44,200 --> 01:28:54,460 Let's uncomment our mode of adding contacts. 1487 01:28:54,460 --> 01:28:57,720 And so right now, I can't run this at the command line, 1488 01:28:57,720 --> 01:29:00,540 because we're using this import syntax. 1489 01:29:00,540 --> 01:29:08,060 But our application state should be some contacts where the three contacts are 1490 01:29:08,060 --> 01:29:12,200 myself twice and David once. 1491 01:29:12,200 --> 01:29:17,522 And now we can go ahead and read from our store in our React application. 1492 01:29:17,522 --> 01:29:19,730 So if you remember what our application looks like is 1493 01:29:19,730 --> 01:29:21,800 we just have a bunch of contacts. 1494 01:29:21,800 --> 01:29:25,310 And these contacts can be toggleable, but they just really 1495 01:29:25,310 --> 01:29:29,200 just show on this simple list page. 1496 01:29:29,200 --> 01:29:34,970 And so to dive back into the code from the past few lectures, 1497 01:29:34,970 --> 01:29:38,345 where do we actually get those contacts? 1498 01:29:38,345 --> 01:29:41,930 Is it in the contact list file? 1499 01:29:41,930 --> 01:29:45,710 No, everything is in our app, dot, js file. 1500 01:29:45,710 --> 01:29:49,620 1501 01:29:49,620 --> 01:29:51,680 Right now, we're just implementing our contacts 1502 01:29:51,680 --> 01:29:55,710 from our random-contact generator file that we wrote a few weeks ago. 1503 01:29:55,710 --> 01:30:02,660 But ultimately, we're setting states in our application class and passing that 1504 01:30:02,660 --> 01:30:06,080 through our navigation via screen props, and then 1505 01:30:06,080 --> 01:30:13,619 accessing it in our relevant page by doing, like, this, dot, props, dot, 1506 01:30:13,619 --> 01:30:17,900 navigator, dot, getParam, dot, whatever. 1507 01:30:17,900 --> 01:30:24,314 And so it's a lot of work just to get our single key there. 1508 01:30:24,314 --> 01:30:25,730 But there's actually more to that. 1509 01:30:25,730 --> 01:30:29,110 We're also passing our contacts to every single other page in our application, 1510 01:30:29,110 --> 01:30:31,150 even the ones that don't care about it. 1511 01:30:31,150 --> 01:30:33,890 And so now what's nice about Redux is we can only 1512 01:30:33,890 --> 01:30:38,570 listen to that information in the pages that we actively 1513 01:30:38,570 --> 01:30:40,130 care about the information. 1514 01:30:40,130 --> 01:30:46,700 And so we don't really care about contacts in all of our pages, right? 1515 01:30:46,700 --> 01:30:49,800 We only care about it in the page that displays them. 1516 01:30:49,800 --> 01:30:57,940 And so let's delete this code that passes the contacts as a screen 1517 01:30:57,940 --> 01:31:00,290 prop to every single page. 1518 01:31:00,290 --> 01:31:02,450 So if you remember, back a few weeks ago, 1519 01:31:02,450 --> 01:31:06,036 Brent was saying that there's a better way than passing 1520 01:31:06,036 --> 01:31:07,160 screen props to every page. 1521 01:31:07,160 --> 01:31:09,618 And he used that word Redux, which we didn't know what that 1522 01:31:09,618 --> 01:31:11,180 meant a few weeks ago, but now we do. 1523 01:31:11,180 --> 01:31:13,820 Now there's actually a way where we can say, 1524 01:31:13,820 --> 01:31:17,360 oh, this information is only relevant to this particular component. 1525 01:31:17,360 --> 01:31:19,325 And so now in that particular component, we 1526 01:31:19,325 --> 01:31:21,200 can just have it listen directly to the state 1527 01:31:21,200 --> 01:31:26,310 without having to pass that state to every single component. 1528 01:31:26,310 --> 01:31:29,480 And again, how are we going to get that information 1529 01:31:29,480 --> 01:31:31,130 from the store to our components? 1530 01:31:31,130 --> 01:31:33,385 Well, we can use store, dot, getState. 1531 01:31:33,385 --> 01:31:34,260 And so let's do that. 1532 01:31:34,260 --> 01:31:38,190 1533 01:31:38,190 --> 01:31:43,160 So our screen called ContactListScreen is where 1534 01:31:43,160 --> 01:31:45,500 we're getting that information, right? 1535 01:31:45,500 --> 01:31:54,440 Now, what we're doing is this, dot, props, dot, screenProps, dot, contacts. 1536 01:31:54,440 --> 01:31:58,790 And so let's actually do something different. 1537 01:31:58,790 --> 01:32:01,010 So rather than looking at our screenProps, 1538 01:32:01,010 --> 01:32:11,840 let's do import store for Redux, slash, store. 1539 01:32:11,840 --> 01:32:13,880 So now that's our store. 1540 01:32:13,880 --> 01:32:16,730 How do we get our information? 1541 01:32:16,730 --> 01:32:24,404 Well, we can just do const contacts is store, dot, getState-- 1542 01:32:24,404 --> 01:32:26,320 which is how we get the state from our store-- 1543 01:32:26,320 --> 01:32:29,010 dot, contacts. 1544 01:32:29,010 --> 01:32:32,580 Because getState returns the entire state of our application. 1545 01:32:32,580 --> 01:32:36,050 And if you remember, what that looks like is user with some user information 1546 01:32:36,050 --> 01:32:38,240 and contacts with our list of contacts. 1547 01:32:38,240 --> 01:32:40,760 We only care about the dot contacts part. 1548 01:32:40,760 --> 01:32:44,190 And so we can grab that and just pass that directly to here. 1549 01:32:44,190 --> 01:32:51,060 1550 01:32:51,060 --> 01:32:53,794 And so now, hopefully-- 1551 01:32:53,794 --> 01:32:56,770 1552 01:32:56,770 --> 01:32:57,800 so AddContact. 1553 01:32:57,800 --> 01:33:02,410 Oh, I uncommented something without importing what it needed. 1554 01:33:02,410 --> 01:33:03,810 So let's just go back to Redux. 1555 01:33:03,810 --> 01:33:07,830 1556 01:33:07,830 --> 01:33:10,560 So I ended up using addContact here without importing it. 1557 01:33:10,560 --> 01:33:15,030 And so if I wanted to use that addContact action creator, 1558 01:33:15,030 --> 01:33:19,560 I need to first import addContact from our actions file. 1559 01:33:19,560 --> 01:33:23,380 1560 01:33:23,380 --> 01:33:29,240 And so now, we can see that we're creating our-- 1561 01:33:29,240 --> 01:33:35,030 people are showing up, however their phone numbers are not-- 1562 01:33:35,030 --> 01:33:37,418 let's see why that's happening. 1563 01:33:37,418 --> 01:33:45,900 1564 01:33:45,900 --> 01:33:48,260 So we're creating people with name and numbers. 1565 01:33:48,260 --> 01:33:53,690 And I assume that row is actually looking at a different-- 1566 01:33:53,690 --> 01:33:56,630 I think it's looking for a prop called phone, 1567 01:33:56,630 --> 01:34:03,220 so let's actually just change number to phone. 1568 01:34:03,220 --> 01:34:09,130 1569 01:34:09,130 --> 01:34:11,620 And so now, we should be getting those phone numbers. 1570 01:34:11,620 --> 01:34:16,630 So basically we had a bug where I thought contacts were name and number, 1571 01:34:16,630 --> 01:34:20,740 but we actually defined a contact to be name and phone. 1572 01:34:20,740 --> 01:34:25,240 And so by storing the correct data, we then get it back in our application 1573 01:34:25,240 --> 01:34:26,430 here. 1574 01:34:26,430 --> 01:34:26,930 Cool. 1575 01:34:26,930 --> 01:34:33,730 So this is awesome because if you ignore the keys that we didn't add, now 1576 01:34:33,730 --> 01:34:37,780 we're getting that data in only the list that cares about it. 1577 01:34:37,780 --> 01:34:41,500 So the separate screens that don't care about the contacts 1578 01:34:41,500 --> 01:34:43,720 don't get access to our contacts. 1579 01:34:43,720 --> 01:34:46,510 The scope of that information is limited only 1580 01:34:46,510 --> 01:34:50,750 to the component that cares about it, which is a good thing. 1581 01:34:50,750 --> 01:34:54,940 So now, how are we going to update that store? 1582 01:34:54,940 --> 01:34:58,360 So if you remember back to the drawing of Redux, 1583 01:34:58,360 --> 01:35:02,470 what's the only way to update a store? 1584 01:35:02,470 --> 01:35:06,226 Well, it's by dispatching an action. 1585 01:35:06,226 --> 01:35:07,600 And how do we dispatch an action? 1586 01:35:07,600 --> 01:35:09,640 Well, we do it from a view. 1587 01:35:09,640 --> 01:35:14,500 And so we can go ahead and add that action to our view. 1588 01:35:14,500 --> 01:35:17,060 1589 01:35:17,060 --> 01:35:19,240 So we need to use store, dot, dispatch in order 1590 01:35:19,240 --> 01:35:22,765 to send that action to our store. 1591 01:35:22,765 --> 01:35:24,880 We need to do store, dot, dispatch in order 1592 01:35:24,880 --> 01:35:26,090 to send that information to our store. 1593 01:35:26,090 --> 01:35:27,339 And so let's actually do that. 1594 01:35:27,339 --> 01:35:31,030 1595 01:35:31,030 --> 01:35:34,240 So in our previous iteration of the app-- 1596 01:35:34,240 --> 01:35:39,416 1597 01:35:39,416 --> 01:35:41,290 earlier what we were doing is we were passing 1598 01:35:41,290 --> 01:35:45,370 this function called Add Contact to every single one of our screens 1599 01:35:45,370 --> 01:35:48,080 via this thing called screen prompts. 1600 01:35:48,080 --> 01:35:55,600 But now, we can do better by only passing the Add Contact function 1601 01:35:55,600 --> 01:35:57,190 to the screen that cares about it. 1602 01:35:57,190 --> 01:35:58,230 And what screen is that? 1603 01:35:58,230 --> 01:36:04,810 Well, it's the one called Add ContactScreen. 1604 01:36:04,810 --> 01:36:08,320 And if you remember right now, the way that we're handling the Submit 1605 01:36:08,320 --> 01:36:11,410 is by doing this dot props, dot, screenProps, dot addContact, 1606 01:36:11,410 --> 01:36:14,320 and then we pass form state. 1607 01:36:14,320 --> 01:36:16,540 But we have a better way to do that now. 1608 01:36:16,540 --> 01:36:19,390 We can actually just directly dispatch an action. 1609 01:36:19,390 --> 01:36:20,870 And so let's do that. 1610 01:36:20,870 --> 01:36:25,750 So first, we need to import store from our store. 1611 01:36:25,750 --> 01:36:28,872 1612 01:36:28,872 --> 01:36:30,830 And we also need our action that we care about. 1613 01:36:30,830 --> 01:36:39,040 So let's import Add Contact from Redux actions. 1614 01:36:39,040 --> 01:36:41,385 1615 01:36:41,385 --> 01:36:43,510 And so now, what do we want to do for handleSubmit? 1616 01:36:43,510 --> 01:36:48,144 So rather than this, we can actually just do store, dot, dispatch. 1617 01:36:48,144 --> 01:36:49,310 And what are we dispatching? 1618 01:36:49,310 --> 01:36:51,726 Well, it's the same thing that we were dispatching before. 1619 01:36:51,726 --> 01:36:54,430 It's an action called addContact, or action creator 1620 01:36:54,430 --> 01:36:56,590 I should say-- called addContact. 1621 01:36:56,590 --> 01:36:58,829 And what is our action? 1622 01:36:58,829 --> 01:37:00,120 Well, it's just our form state. 1623 01:37:00,120 --> 01:37:06,920 1624 01:37:06,920 --> 01:37:08,512 And that's it. 1625 01:37:08,512 --> 01:37:11,220 Actually, our form state has more information than we care about. 1626 01:37:11,220 --> 01:37:14,360 So if we really want to be succinct, we can 1627 01:37:14,360 --> 01:37:17,300 say the name is formState, dot, name. 1628 01:37:17,300 --> 01:37:21,060 1629 01:37:21,060 --> 01:37:26,170 And our phone is formState, dot, phone. 1630 01:37:26,170 --> 01:37:30,100 1631 01:37:30,100 --> 01:37:35,440 And now, presumably we did what we wanted to do. 1632 01:37:35,440 --> 01:37:36,700 So let's go and check. 1633 01:37:36,700 --> 01:37:38,580 We can add a new contact. 1634 01:37:38,580 --> 01:37:42,922 Let's add Yowon Y, and give a phone number. 1635 01:37:42,922 --> 01:37:43,630 What do you know? 1636 01:37:43,630 --> 01:37:45,460 He has the same phone number as I do. 1637 01:37:45,460 --> 01:37:48,740 And submit-- oh, wait a second. 1638 01:37:48,740 --> 01:37:49,840 Yowon didn't show up. 1639 01:37:49,840 --> 01:37:52,360 1640 01:37:52,360 --> 01:37:55,890 But if we toggle contacts and reappear, look, there-- oh, I spelled name wrong. 1641 01:37:55,890 --> 01:38:00,970 But there is what should be Yowon. 1642 01:38:00,970 --> 01:38:06,140 So why didn't he show up the first time? 1643 01:38:06,140 --> 01:38:10,805 So there's one thing that we're missing as we've added Redux to our app. 1644 01:38:10,805 --> 01:38:13,186 It's that we're not getting the application 1645 01:38:13,186 --> 01:38:14,560 to update when the store changes. 1646 01:38:14,560 --> 01:38:20,680 And this is a bug that we've seen before, but this time it's different. 1647 01:38:20,680 --> 01:38:26,586 And so how might we get our application to automatically re-render 1648 01:38:26,586 --> 01:38:28,085 every single time our store changes? 1649 01:38:28,085 --> 01:38:30,740 1650 01:38:30,740 --> 01:38:36,890 Well, presumably, we would want to use the other part of Redux that 1651 01:38:36,890 --> 01:38:39,540 calls a callback every single time it adds, 1652 01:38:39,540 --> 01:38:42,770 which is a lot of extra work for us. 1653 01:38:42,770 --> 01:38:46,470 I wonder if there's a way that we could do that better. 1654 01:38:46,470 --> 01:38:50,240 So we've talked about this thing in a few lectures 1655 01:38:50,240 --> 01:38:54,360 before, this thing called a HOC, or in other words a higher-order component. 1656 01:38:54,360 --> 01:38:57,680 What a higher-order component is it takes a component as an argument, 1657 01:38:57,680 --> 01:39:01,780 or it returns a component as a result of a function. 1658 01:39:01,780 --> 01:39:03,650 And so we could actually create a HOC that 1659 01:39:03,650 --> 01:39:07,490 does a lot of what we've just done manually for us. 1660 01:39:07,490 --> 01:39:09,800 What if we created a HOC that is the following? 1661 01:39:09,800 --> 01:39:11,550 It checks for state updates automatically, 1662 01:39:11,550 --> 01:39:17,390 or it subscribes to them, and then it passes new props to when that happens. 1663 01:39:17,390 --> 01:39:20,770 And wouldn't it be also cool if rather than having to go bind 1664 01:39:20,770 --> 01:39:25,280 our action creators ourselves, like we did here-- 1665 01:39:25,280 --> 01:39:27,890 or here, this line-- 1666 01:39:27,890 --> 01:39:31,040 what if we instead did that automatically? 1667 01:39:31,040 --> 01:39:34,670 What if our HOC for us automatically bound our action creators 1668 01:39:34,670 --> 01:39:37,760 to our dispatch function for us? 1669 01:39:37,760 --> 01:39:39,690 That would be really cool. 1670 01:39:39,690 --> 01:39:44,570 Then we wouldn't need to subscribe to store updates. 1671 01:39:44,570 --> 01:39:47,081 Our higher-order component can do that for us. 1672 01:39:47,081 --> 01:39:48,830 And when I say our higher-order component, 1673 01:39:48,830 --> 01:39:52,590 I mean the one that React conveniently implemented for us. 1674 01:39:52,590 --> 01:39:55,730 And so if we check this thing called React Redux, 1675 01:39:55,730 --> 01:39:59,270 we see some official React bindings for Redux, 1676 01:39:59,270 --> 01:40:00,980 which gives us a few cool things. 1677 01:40:00,980 --> 01:40:02,710 And by a few, I mean two. 1678 01:40:02,710 --> 01:40:06,020 We have this thing called a provider and this thing called connect. 1679 01:40:06,020 --> 01:40:10,880 And if we look at what this is, a provider-- 1680 01:40:10,880 --> 01:40:15,470 it basically handles the binding for us. 1681 01:40:15,470 --> 01:40:19,190 It listens to a store, and it'll see when it updates. 1682 01:40:19,190 --> 01:40:23,480 And then this thing called connect is a higher-order component, 1683 01:40:23,480 --> 01:40:28,290 so it takes a component as an argument. 1684 01:40:28,290 --> 01:40:33,110 Or actually it takes some configuration as an argument, returns a function 1685 01:40:33,110 --> 01:40:36,530 that's now expecting a component as an argument. 1686 01:40:36,530 --> 01:40:38,700 We'll see exactly what that means in a second. 1687 01:40:38,700 --> 01:40:40,920 But basically it does a lot of things for us. 1688 01:40:40,920 --> 01:40:45,680 It passes only the relevant props that we care about. 1689 01:40:45,680 --> 01:40:48,920 So this function-- the first argument we pass 1690 01:40:48,920 --> 01:40:52,490 it is this thing called mapStateToProps, which is actually a function that 1691 01:40:52,490 --> 01:40:58,910 takes our entire application state and will return an object of props 1692 01:40:58,910 --> 01:41:03,830 that we care about, meaning for this particular component, 1693 01:41:03,830 --> 01:41:05,990 it doesn't care about our entire application state. 1694 01:41:05,990 --> 01:41:08,090 It only cares about a subset of it. 1695 01:41:08,090 --> 01:41:14,600 And for a particular example, our ContactListScreen 1696 01:41:14,600 --> 01:41:18,290 doesn't care about our entire state of our component. 1697 01:41:18,290 --> 01:41:21,560 We only care about this one key called contacts. 1698 01:41:21,560 --> 01:41:24,740 And so it would be great if we had in higher-order function-- 1699 01:41:24,740 --> 01:41:28,400 which handles this for us. 1700 01:41:28,400 --> 01:41:29,820 It listens to the store. 1701 01:41:29,820 --> 01:41:32,770 It grabs the state, and it only passes contacts down. 1702 01:41:32,770 --> 01:41:35,690 And the way it does it is a prop. 1703 01:41:35,690 --> 01:41:39,140 And so this connect function implements that behavior for us. 1704 01:41:39,140 --> 01:41:42,080 We pass a function that maps our application 1705 01:41:42,080 --> 01:41:44,450 state to own the props that we care about, 1706 01:41:44,450 --> 01:41:46,770 and then it passes those down as props for us. 1707 01:41:46,770 --> 01:41:52,000 And so let's go ahead and first install this library so that we can use it. 1708 01:41:52,000 --> 01:41:54,720 And if you haven't, install React, Redux. 1709 01:41:54,720 --> 01:42:02,210 1710 01:42:02,210 --> 01:42:06,100 And as you remember, this will also add it to our package, dot, json. 1711 01:42:06,100 --> 01:42:15,280 So if I look at our package, dot, json, I can see React, Redux got added. 1712 01:42:15,280 --> 01:42:18,260 And now, we can go ahead and use that connect function. 1713 01:42:18,260 --> 01:42:25,470 So in our ContactListScreen, rather than importing the store itself, 1714 01:42:25,470 --> 01:42:27,990 let's actually only import connect. 1715 01:42:27,990 --> 01:42:33,490 1716 01:42:33,490 --> 01:42:40,060 So we now have access to this higher-order component called connect, 1717 01:42:40,060 --> 01:42:41,710 which we can now use. 1718 01:42:41,710 --> 01:42:45,540 So rather than default exporting this entire class, 1719 01:42:45,540 --> 01:42:50,620 let's actually wrap it in a higher-order component. 1720 01:42:50,620 --> 01:42:54,430 So let's down here do export, default, connect. 1721 01:42:54,430 --> 01:42:56,500 We're going to pass it something. 1722 01:42:56,500 --> 01:42:59,440 And then we're going to pass the class that we created, 1723 01:42:59,440 --> 01:43:01,390 so this thing called ContactListScreen. 1724 01:43:01,390 --> 01:43:04,862 1725 01:43:04,862 --> 01:43:05,820 And what do we pass it? 1726 01:43:05,820 --> 01:43:10,360 Well, we pass it a function that maps our application state to our props. 1727 01:43:10,360 --> 01:43:15,670 And so we can do const mapStateToProps. 1728 01:43:15,670 --> 01:43:17,710 I can really call this whatever I want. 1729 01:43:17,710 --> 01:43:21,190 Let's have it take our entire application state 1730 01:43:21,190 --> 01:43:26,720 and only return the subset that we care about, or in other words, the contacts. 1731 01:43:26,720 --> 01:43:30,160 And so a prop called contacts will get mapped to sate, 1732 01:43:30,160 --> 01:43:34,900 dot, contacts, and then of course pass that function into connect. 1733 01:43:34,900 --> 01:43:38,320 1734 01:43:38,320 --> 01:43:42,940 So again, the first argument to connect is just a function, 1735 01:43:42,940 --> 01:43:44,810 which I happen to call mapStateToProps. 1736 01:43:44,810 --> 01:43:46,420 We can call it whatever you want. 1737 01:43:46,420 --> 01:43:49,980 We can call it getState-- 1738 01:43:49,980 --> 01:43:51,030 or PropsFromState. 1739 01:43:51,030 --> 01:43:54,280 1740 01:43:54,280 --> 01:43:56,950 But I'll just follow convention and call it mapStateToProps, 1741 01:43:56,950 --> 01:44:00,340 which takes the entire application state and returns 1742 01:44:00,340 --> 01:44:02,390 a subset that we care about, or in other words, 1743 01:44:02,390 --> 01:44:06,850 the prop contacts, which maps to state, dot, contacts. 1744 01:44:06,850 --> 01:44:09,100 And then in here, we no longer have to do that. 1745 01:44:09,100 --> 01:44:15,880 Now we just do this, dot, props, dot, contacts. 1746 01:44:15,880 --> 01:44:19,120 Because what this higher-order function does is it 1747 01:44:19,120 --> 01:44:22,540 listens to our application state. 1748 01:44:22,540 --> 01:44:25,030 It will automatically update as the state updates, 1749 01:44:25,030 --> 01:44:27,470 and it will pass down some number of props. 1750 01:44:27,470 --> 01:44:31,176 And the props are just contacts for now. 1751 01:44:31,176 --> 01:44:32,050 And what is contacts? 1752 01:44:32,050 --> 01:44:34,960 Well, it's whatever the state value of contacts is. 1753 01:44:34,960 --> 01:44:38,280 1754 01:44:38,280 --> 01:44:40,470 And so that is done. 1755 01:44:40,470 --> 01:44:46,660 Unfortunately, it doesn't quite work, because it 1756 01:44:46,660 --> 01:44:51,620 doesn't know what our store is. 1757 01:44:51,620 --> 01:44:55,410 And so now we also have to use the other part of React Redux 1758 01:44:55,410 --> 01:44:58,210 and let our application know what our store is. 1759 01:44:58,210 --> 01:45:04,130 And that is through that component called Provider. 1760 01:45:04,130 --> 01:45:13,150 So if we import Provider from React, Redux, what that does 1761 01:45:13,150 --> 01:45:18,160 is it provides our app with a concept of what our Redux store is. 1762 01:45:18,160 --> 01:45:21,454 So we can just wrap our entire application in this provider 1763 01:45:21,454 --> 01:45:22,870 and let it know what our store is. 1764 01:45:22,870 --> 01:45:29,240 1765 01:45:29,240 --> 01:45:33,740 And this component will provide any of its children with our store. 1766 01:45:33,740 --> 01:45:40,700 And so our store, we should just import from Redux, or the reduction 1767 01:45:40,700 --> 01:45:43,910 implementation that we wrote. 1768 01:45:43,910 --> 01:45:49,100 And now, the store is passed to any of the connect functions that we have. 1769 01:45:49,100 --> 01:45:56,130 And the connect function, which we wrote in ContactListScreen, 1770 01:45:56,130 --> 01:46:01,430 it can now listen to the store and map any changes in the application state 1771 01:46:01,430 --> 01:46:05,250 to props that it passes to this ContactListScreen, which we then 1772 01:46:05,250 --> 01:46:10,190 listen to to fill our list. 1773 01:46:10,190 --> 01:46:17,300 And so now we see that it's been sent here, which is cool. 1774 01:46:17,300 --> 01:46:20,550 Lastly, real quick. 1775 01:46:20,550 --> 01:46:22,850 What it also does is we can automatically 1776 01:46:22,850 --> 01:46:25,490 bind our action creators to dispatch. 1777 01:46:25,490 --> 01:46:31,340 And so a quick example of that is in our addContact screen. 1778 01:46:31,340 --> 01:46:34,080 Currently we're not doing any binding at all. 1779 01:46:34,080 --> 01:46:38,330 We're just passing addContact, the return value of that, 1780 01:46:38,330 --> 01:46:40,240 straight to store, dot, dispatch. 1781 01:46:40,240 --> 01:46:44,900 And it turns out, rather than doing that manually, we can just 1782 01:46:44,900 --> 01:46:52,740 import connect from React, Redux. 1783 01:46:52,740 --> 01:46:57,710 And rather than default exporting this entire class, 1784 01:46:57,710 --> 01:47:04,820 we can just export a wrapped version of this. 1785 01:47:04,820 --> 01:47:08,240 So we'll pass connect, some configuration, 1786 01:47:08,240 --> 01:47:10,460 and then pass it our addContact screen. 1787 01:47:10,460 --> 01:47:14,664 1788 01:47:14,664 --> 01:47:16,330 And connect takes a couple of arguments. 1789 01:47:16,330 --> 01:47:19,740 The first one is mapStateToProps. 1790 01:47:19,740 --> 01:47:25,360 Our addContacts screen doesn't care about any of our application states. 1791 01:47:25,360 --> 01:47:27,970 So let's just pass some null value there. 1792 01:47:27,970 --> 01:47:30,360 But it does care about our actions. 1793 01:47:30,360 --> 01:47:35,100 And so we can pass an object into our second argument here, 1794 01:47:35,100 --> 01:47:38,530 and it will automatically bind our action creators with dispatch. 1795 01:47:38,530 --> 01:47:41,710 And so if I did something like addContact, 1796 01:47:41,710 --> 01:47:44,152 so we're going to get a prop called addContact. 1797 01:47:44,152 --> 01:47:45,360 What's its value going to be? 1798 01:47:45,360 --> 01:47:48,930 Well, it's going to be addContact, which is the function that we 1799 01:47:48,930 --> 01:47:53,070 imported from our Redux actions. 1800 01:47:53,070 --> 01:48:00,510 And then it'll actually just pass as a prop to our component. 1801 01:48:00,510 --> 01:48:08,050 So we can do this, dot, props, dot, addContact, 1802 01:48:08,050 --> 01:48:13,660 which will automatically dispatch that up for us, because it 1803 01:48:13,660 --> 01:48:18,700 gets automatically bound by connect. 1804 01:48:18,700 --> 01:48:21,010 And if you want to read more about how that happens, 1805 01:48:21,010 --> 01:48:23,410 the documentation is linked in the slide. 1806 01:48:23,410 --> 01:48:32,730 And now, just to ensure this works, we can go ahead and add Yowon Y here 1807 01:48:32,730 --> 01:48:36,270 with a phone number like so. 1808 01:48:36,270 --> 01:48:37,350 Submit. 1809 01:48:37,350 --> 01:48:38,450 And look at that. 1810 01:48:38,450 --> 01:48:44,700 Our application automatically updated due to a update in our application 1811 01:48:44,700 --> 01:48:46,150 state. 1812 01:48:46,150 --> 01:48:50,280 So this was a quick example of how we use Redux and React. 1813 01:48:50,280 --> 01:48:52,620 And next week, we'll dive even farther into Redux 1814 01:48:52,620 --> 01:48:56,370 and show how we handle stuff like asynchronous actions 1815 01:48:56,370 --> 01:48:57,840 once we do some data-fetching. 1816 01:48:57,840 --> 01:49:00,890 So thanks, I'll see you next week. 1817 01:49:00,890 --> 01:49:02,151