Using Redux in Angular 2+ Apps | Mosh

Programming with Mosh · Intermediate ·🌐 Frontend Engineering ·9y ago

Key Takeaways

The video demonstrates how to use Redux in Angular 2+ apps, covering the basics of Redux, its benefits, and how to implement it in an Angular app. It also covers the concepts of state management, pure functions, and time travel debugging.

Full Transcript

[Music] so what is Redux Redux is a library that helps you manage the state of your application and it's something that you should use in medium to large single page applications with complex data flows so if you're building a simple application with simple data flow you don't necessarily need Redux and in fact Redux can add extra unnecessary complex your application so what do I mean by these large single page applications well in a typical angular app without the Redux AR without the Redux architecture you know that each component maintains the state and the logic behind a view this model aligns perfectly with the encapsulation principle of objectoriented programming however it can be a problem when you have multiple views that are working with the same piece of data and do not have a parent child relationship in these situations we often have multiple copies of the same data that are independent of each other so when a view updates a model we need to do some extra work to keep the other views in sync for example think of Facebook on Facebook we have three views that represent the current state of users messages on the navigation bar we have this icon that shows the number of new messages and if we're on the messages page we have a view like this and irrespective of what page we are on we can also have multiple chat tabs on the bottom of the screen these are independent views that need to be in sync and what is important here is that they do not have a parent child relationship so this navigation bar is not a parent or child of other views here if it was then passing data would be simple you would simply use the input properties of the child components to pass the data down the sub tree but since these views are independent if you want to keep them in sync we have to do some extra work a common solution is to use events and sooner or later that will turn into an event spaghetti in the large code base we have events published all over the place and then to cheack what happens to the application State we have to jump all over the code to see what's going on the problem with this approach is that the data can be updated in an unpredictable way when there is a bug we have to jump all over the code to figure out how the data is flowing and how the application state is updated in multiple places so it's unpredictable also adding a new feature becomes a challenge because once again we don't know what is the impact of this new feature on the application state if it's touching the same piece of data that is in different places that needs to be kept in sync again we have to do a lot of hard work so Facebook had this problem back in 2014 and that's why they introduced the flux architecture now Redux is a simplified and lightweight implementation of this architecture that provides a clean and elegant solution to this problem maintaining the application state in a predictable way so there are no surprises now apart from this Redux provides a number of other benefits the first one is that it decouples your applic apption from a presentation framework like angular so you can Implement a big chunk of your application and its presentation logic using simple functions that are completely decoupled from angular or any other presentation Frameworks and then you can decide if you want to use angular or maybe you want to use react so it allows you to postpone decisions about external libraries and Frameworks which is one of the attributes of clean architecture as you might have heard heard from Uncle Bob the second benefit is that it makes it easier to unit test your application without mocks spies and any other tricks that can make testing both complex and error prone because Redux is heavily based on functional programming so as you will see in this section we'll be writing simple functions that take a state and return a new state that's all these functions are really easy to test and this means you can write your tests before your production code which basically means means test driven development or tdd the third benefit is that you can get some really cool tools as part of your development one such example is Redux developer tools extension that you can add to Chrome Firefox and other browsers it makes it incredibly easy to debug your application by allowing you to inspect the application state in such a way that we have never seen before this is actually one of the features that I was really impressed with and you're going to see that in this section and the last benefit is that Redux makes it incredibly easy to implement features like undo and redo so if you need these functions in your application yes you can implement it without Redux but using Redux makes your life much easier now all these fancy benefits of course they come with a cost just like many other architectural patterns you're going to write a bit more code and you will have more moving Parts in your application so use Redux only if you're building a medium to large single page application with complex views and data flows here are some scenarios you have independent copies of the same data in multiple places you have multiple views that need to work with the same data and be in sync users can collaborate and work on the same piece of data so data can be changed by user a and at the same time user B can change the same data or data can be up updated by multiple actors so it can be changed as a result of user actions and at the same time it may arrive from the server either via polling or push notifications so if you have these scenarios in your application you would potentially benefit from Redux so remember when building a new app you don't need to automatically reach for Redux you can always start simple and as your application grows then you can refactor existing components and use Redux to manage the application date in a predictable and deterministic way next we're going to look at the building blocks of Redux in Redux we have three pieces the store actions and reducers let's explore these one by one the store is a single JavaScript object that contains the state of the application you can think of it as a local client side database so here we can have properties like the list of messages number of new messages to be displayed on the navigation bar whether chat sounds are enabled and so on different views and components use different parts or different slices of the application State depending on their functionality and this also means if different components need to work with the same slice there is only one copy of that slice throughout the application so once a component modifies that slice the changes are immediately visible to other components we don't have multiple independent copies now the first question you might have is wouldn't this consume too much memory not really unless you're storing 10,000 or more objects in this store and then I would ask you why would you do that anyway so for the most part it's okay to have a single object to store the application State the second piece is the actions actions are plain Javas script objects that represent something that has happened in the application so semantically they're more like events if you have some background in cqrs architectural style you should know the difference between commands and events commands or actions represent something that should happen like posting a message whereas events indicate that something has happened like a message was posted actions in Redux are semantically events here are a couple of examples when the user reads a message we can represent this event using an action like this as another example if the user posts a message we can have an action like this so these are simple data structures and don't have any logic and by convention we use a type property to specify the type of each action now an action can have additional properties related to the event that just happened and the last piece reducer now reducer is a term that often confuses a lot of beginners to Redux unfortunately the terms used in the Redux Library are not very helpful so actions are really events and reducers can be a little bit confusing to beginners now reducer is basically a function that specifies how the state changes in response to an action you can think of it as an action Handler or an event handler that determines how this state is changed now what is critical here is that the reducer does not modify the state it only Returns the new state and then the store will internally update the state so nowhere in the application we're going to directly modify the state this is the responsibility of the store it keeps the state and updates it whenever necessary so these are the building blocks of Redux now these reducers should be pure functions but what do I mean by pure well that's the topic for the next lecture so what is a pure function well a function is pure if we give it the same input we always get the same output no matter how many times we call that function so it shouldn't have any side effects let's take a look at a few examples so this function is impure because every time we call it it's modifying its AR argument so if the value of the count property of the input is initially zero and we call this function 10 times to incremented instead of getting one we get 10 so in a pure function we should not mutate or modify any of the arguments here's another example in this function we're making backend calls bya this service and this is an example of a side effect so every time we call this function our application State stored in a database on the server is modified and here is the third example in this function we're updating the value of the count property based on a random number generated by the mass class so with this function if we give it the same input we cannot ensure that we always get the same output the output is different every time because we are using an impure function so in a pure function we should not use mass. random or date. now or any other functions that return a different value every time column now let's take this first example and change it to a pure function so instead of incrementing this count property we return a new object with a count property and the value of this count property would be the value of the original count + 1 if we call this function 10 times and give it the same input we always get the same output so if count is initially zero and we call this function 10 times we'll get one because this function is is not modifying its argument so in Redux our reducers should be pure functions now let's take this example and modify it a little bit so it looks like a reducer function in Redux in Redux reducer functions always take two arguments the current state and an action then based on the action type they return a new state so typically we use a switch statement on the type property of the ction and based on the value of the type property we return a new state so let's imagine action. type is increment then we return a new state with the updated property so we're not going to modify the original state pass to this function now if you have never done functional programming before this concept is new and confusing to you I totally understand that so you might be asking what is the point of this why are we not allowed to mutate or modify by state you always have to return a new state well there are a number of benefits to this approach the first benefit is that pure functions are really easy to test imagine you want to write a test for this function you don't need any mocks any spies or any other tricks you simply call this function give it an input and make an assertion about the output as simple as that the second benefit is that this approach makes it really easy to implement features like undo and redo because we always keep the previous date instead of modifying it and the third benefit is that it gives us a powerful tool which we call time travel debugging so using the tool that I will show you later in this section we can travel back in time and look at our application State as different actions are triggered in the application we can see how the application state is modified in every step and this makes it really easy to find bugs and fix them but once again it only makes sense if you're building a complex application with complex data flow for a calculator application you don't need Redux but if you have complex views complex data structures and things have to be modified in different places then you can look at the application State and see exactly how it's modified all right now let me show you how to add Redux to an angular app there are many implementations for Redux but the two common implementation are ngrx SL store and ng2 D rux these are the most popular ones and they're very very similar in terms of their API ang2 Redux is built on top of the real Redux library and it's compatible with much of the Redux ecosystem it adds bindings for angular 2 so you can easily connect your angular components with Redux ngrx store on the other hand has gone the route of reimplementing the Redux pattern in an angular to and RX friendly way this means it's not compatible with other libraries built for Redux so in this section I'm going to use ng2 D rux but I wanted you to be aware of ngrx store because there are a lot of blog posts and questions on stack Overflow that are centered around this implementation all right now before we get started make sure you have the latest version of angular CLI so on my machine I'm using angular CLI version one beta 26 if yours is older simply do npm install angular-cli DG all right now I'm going to create a new folder Redux D demo go into this folder and run NG in it all right now if you look at package.json you'll notice that we're using angular 2.3.1 this is very important if you want to follow along with this lecture otherwise when you add Redux you're going to get an error in npm because the latest version of Redux is not compatible with older versions of angular so make sure you've got angular 2.3.1 or higher now back in terminal npm install Redux so this is the main Redux library for JavaScript it's got nothing to do with angular then we add a ng2 D Redux which provides an angular module for dependency injection as well as some other helpers that we're going to use in this section so add this to the project now if for any reasons you're having difficulty creating a new angular project and adding these dependencies I've attached this project for you to this lecture so simply download it and then do npm install and then NG serve now now if you head over to Local Host Port 4200 you get our familiar angular 2 app so now let's start implementing Redux in this application first I'm going to go in the source folder under app add a new file store. TS here I'm going to export an interface called I App State so this interface determines the shape of our store for now we're going to leave with empty but as we go through this section we're going to add some properties to this interface so this interface will determine what properties we're going to have in our store now I'm also going to export a function which I call Root reducer so we start with one reducer function here and as our application grows we can break down this function into smaller more maintainable functions each focusing on one domain in the application now as you saw in the last lecture each reducer takes two parameters the current state and an action and it returns a new state so for now I'm just going to return the state that we get here we are not going to implement a switch case here yet that's going to come in the next lecture so this is a very basic reducer it doesn't do anything all right save now let's go to app. module on the top we need to import a couple of types from ng2 D rux so import from ng2 D Redux first one is NG Redux and the second is NG Redux module now we need to import this module into our main module and that's used for dependency injection so NG Redux module now we're going to create a Constructor for app module this Constructor should get an object called NG Redux which is of type NG Redux that we imported on the top now this type is generic so we need to specify a generic parameter here in angle brackets and what we pass here is the interface that we declared earlier so this interface determines the shape of our store so I'm I'm going to go on the top import I App State and root reducer from current folder SL store now back in the Constructor I'm going to use I App State as the generic argument for NG Redux and the final step we use this inur Redux object here and call configure store this is to initialize our store now the first argument to this method should be a root reducer so root reducer and the second argument is our initial store so I'm going to pass an empty JavaScript object this is our store object that will eventually get updated as we go through this section with this if it save the changes and get back to the browser the application should still work and we shouldn't have any errors in the console so let's double check that okay here's the console there's absolutely no errors perfect so we have successfully installed Redux in this project next we're going to work with actions all right now let's see how we can use actions so here in app components template I'm going to add a button call it increment handle the click event and bind this to the increment method of our component I'm also going to add a counter here so when we click this button this counter is going to be incremented now let's go to app component declare counter here and initialize it to zero then add the increment method so in a typical angular app this is how we implement this method we modify the state directly here however when using the Redux architecture we don't modify the state here instead we dispatch an action this action goes in the store the store knows our root reducer so it passes the action to the root reducer and then the reducer looks at the action and based on the type of the action it will return a new state and then the store will update its state internally so let's see how we can implement M this first I'm going to go on top of this file and import NG Redux from ng2 D Redux so this is the primary type that we work with in Redux applications now I'm going to create a Constructor and inject NG Redux here NG Redux now you remember that this is a generic type so here we need to specify a generic argument which is I App State that's the interface that determines the shape of our store so I'm going to import I App State on the top like this now back in the Constructor I'm going to apply the private modifier here so we can access this in the increment method now instead of modifying this directly we're going to call this. injury do. dispatch here we need to pass an action object and as you learned earlier an action is a simple object that has a type property so this is how we dispatch an action now some actions may carry extra data about the event that just happened for example if the user posted a message here you can have properties like body subject and so on but in this example we don't have to worry about that so delete now every time we Define a new action we need to go to our reducer and determine how the state will change in response to that action so let's go to store here I'm going to add a switch statement on action. type and if it's increment I'm going to return a new state with updated counter so currently it's not clear what is the type of this state object so I'm going to apply a type here this should be of type I App State so we get the current state of the store and then we return a new state so again I'm going to add a type here this function will return I App State and now because we need to work with a counter we need to store its current value in the store so in I App State interface I'm going to declare a property counter of type number okay and now in response to the increment action I'm going to return a new object with counter set to state. counter which is the current value of the counter plus one so note that I'm not modifying the original state here I'm returning a new state and the final step earlier in app module here we passed the initial state of our store now we have a red underline here because our store now has a counter property that we have not initialized so back in app module I'm going to set counter to zero so let's quickly review the steps and then I will show you how to improve this code in the app component we injected NG Redux in the Constructor and in the increment method instead of modifying the state directly we dispatched an action then we went to our store we modified the root reducer and added support for the increment action now as part of this we also had to modify I App State so now we have this counter property and finally in the app module we modifi this line here to set the initial state of our store now there are a couple of things we can improve in this code the first issue I see here is the use of this magic string in two different places we have used this in the app component and also in the store now the problem with this is that we have duplicated this in two different places and if we have a typo in the code our code is not going to work so it's better to extract this into one place Define it as a constant so this will we won't have a typo problem and if you want to change this to something else in the future there is only one place we need to change so in the app folder I'm going to add a new file called actions and here I'm going to export a constant called increment and set it to increment now we can replace those two magic strings with this constant so first in the store on the top I'm going to import increment from actions and then I'm going to replace this magic string here increment now to save time I'm going to copy this line and go to app component on the top paste it and once again replace this magic string with a constant that's the first Improvement now the second Improvement you notice that when we changed I app here we had to go to the app module and modify this initial State object here so we are going back and force between different files and this is really not good practice so let's go back to the store here I'm going to export a constant and call it initial State this is of type I App State and I'm going to set this to this object with counter set to zero now next time we're going to modify the I App State interface we can immediately modify this initial state if necessary we don't have to jump back and forth between the store and the app module so now let's go to the app module and import initial state from the store and then replace this object here with initial State now if you run the application at this point and click this button the counter is not incremented because we have only implemented the part for updating the state reading the state from the store is something else and that's what we're going to look at in the next lecture hey thank you for watching my YouTube video my name is MH hamedani and I'm a full stack developer a plural site author and a un instructor with about 14 courses at the time of recording this video so I've got lots of courses on both front end and backend development including C and framework as.net NVC angular architecture unit testing and so on this video you watched is actually part of my angular course on Udi that you can get with a discount using the link in the video description and if you want to see my other courses simply head over to programming withth m.com SLC courses you can also subscribe to my YouTube channel to get free videos every week have a great day and I'll be back soon [Music]

Original Description

🔥Get the COMPLETE COURSE (60% OFF - LIMITED TIME): https://programmingwithmosh.com/courses/angular Redux in Angular4 (Angular2+): Learn what Redux is, when to use and why, and how to implement it in an Angular 2+ app. STAY IN TOUCH https://twitter.com/moshhamedani https://www.facebook.com/programmingwithmosh/
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from Programming with Mosh · Programming with Mosh · 31 of 60

1 6 Visual Studio Tips to Increase Your Productivity | Mosh
6 Visual Studio Tips to Increase Your Productivity | Mosh
Programming with Mosh
2 Visual Studio Keyboard Shortcuts that Speed Up Debugging Applications | Mosh
Visual Studio Keyboard Shortcuts that Speed Up Debugging Applications | Mosh
Programming with Mosh
3 Backbone.js Tutorial Part 2 - Backbone.js Models: Working with Model Attributes
Backbone.js Tutorial Part 2 - Backbone.js Models: Working with Model Attributes
Programming with Mosh
4 Backbone.js Tutorial Part 3 - Backbone.js Models: Model Validation
Backbone.js Tutorial Part 3 - Backbone.js Models: Model Validation
Programming with Mosh
5 Backbone.js Tutorial Part 4 - Backbone.js Models: Model Inheritance
Backbone.js Tutorial Part 4 - Backbone.js Models: Model Inheritance
Programming with Mosh
6 Backbone.js Tutorial Part 1 - Backbone.js Models: Creating Models
Backbone.js Tutorial Part 1 - Backbone.js Models: Creating Models
Programming with Mosh
7 Backbone.js Tutorial Part 5 - Backbone.js Models: Syncing Models with the Server
Backbone.js Tutorial Part 5 - Backbone.js Models: Syncing Models with the Server
Programming with Mosh
8 Backbone.js Tutorial Part 6 - Backbone.js Collections: Creating Collections
Backbone.js Tutorial Part 6 - Backbone.js Collections: Creating Collections
Programming with Mosh
9 Backbone.js Tutorial Part 7 - Backbone.js Collections: Working with Collections
Backbone.js Tutorial Part 7 - Backbone.js Collections: Working with Collections
Programming with Mosh
10 Backbone.js Tutorial Part 8 - Backbone.js Collections: Fetching Collections from the Server
Backbone.js Tutorial Part 8 - Backbone.js Collections: Fetching Collections from the Server
Programming with Mosh
11 Backbone.js Tutorial Part 9 - Backbone.js Views: Creating Views
Backbone.js Tutorial Part 9 - Backbone.js Views: Creating Views
Programming with Mosh
12 Backbone.js Tutorial Part 10 - Backbone.js Views: Passing Data to Views
Backbone.js Tutorial Part 10 - Backbone.js Views: Passing Data to Views
Programming with Mosh
13 Backbone.js Tutorial Part 11 - Backbone.js Views: Handling the DOM Events
Backbone.js Tutorial Part 11 - Backbone.js Views: Handling the DOM Events
Programming with Mosh
14 Backbone.js Tutorial Part 12 - Backbone.js Views: Handling the Model Events
Backbone.js Tutorial Part 12 - Backbone.js Views: Handling the Model Events
Programming with Mosh
15 Backbone.js Tutorial Part 13 - Backbone.js Views: Handling Collection Events
Backbone.js Tutorial Part 13 - Backbone.js Views: Handling Collection Events
Programming with Mosh
16 Backbone.js Tutorial Part 14 - Backbone.js Views: Templating
Backbone.js Tutorial Part 14 - Backbone.js Views: Templating
Programming with Mosh
17 Clean Code: Learn to write clean, maintainable and robust code
Clean Code: Learn to write clean, maintainable and robust code
Programming with Mosh
18 C# Events and Delegates Made Simple | Mosh
C# Events and Delegates Made Simple | Mosh
Programming with Mosh
19 C# Generics Tutorial: Whats and Whys | Mosh
C# Generics Tutorial: Whats and Whys | Mosh
Programming with Mosh
20 Debugging C# Code in Visual Studio | Mosh
Debugging C# Code in Visual Studio | Mosh
Programming with Mosh
21 Repository Pattern with C# and Entity Framework, Done Right | Mosh
Repository Pattern with C# and Entity Framework, Done Right | Mosh
Programming with Mosh
22 Angular 2 Tutorial for Beginners: Learn Angular 2 from Scratch | Mosh
Angular 2 Tutorial for Beginners: Learn Angular 2 from Scratch | Mosh
Programming with Mosh
23 Architecture of Angular 2+ Apps
Architecture of Angular 2+ Apps
Programming with Mosh
24 Working with Components in Angular
Working with Components in Angular
Programming with Mosh
25 C# Tutorial For Beginners - Learn C# Basics in 1 Hour
C# Tutorial For Beginners - Learn C# Basics in 1 Hour
Programming with Mosh
26 Difference between Junior and Senior Developers
Difference between Junior and Senior Developers
Programming with Mosh
27 Step-by-step ASP.NET MVC Tutorial for Beginners | Mosh
Step-by-step ASP.NET MVC Tutorial for Beginners | Mosh
Programming with Mosh
28 [Pluralsight]: Become a Full-stack .NET Developer
[Pluralsight]: Become a Full-stack .NET Developer
Programming with Mosh
29 Xamarin Forms Tutorial: Build Native Mobile Apps with C#
Xamarin Forms Tutorial: Build Native Mobile Apps with C#
Programming with Mosh
30 Value Types and Reference Types in JavaScript
Value Types and Reference Types in JavaScript
Programming with Mosh
Using Redux in Angular 2+ Apps | Mosh
Using Redux in Angular 2+ Apps | Mosh
Programming with Mosh
32 Testing Angular 2+ Apps with Jasmine and Karma | Mosh
Testing Angular 2+ Apps with Jasmine and Karma | Mosh
Programming with Mosh
33 Profile and optimize your Angular 2 apps
Profile and optimize your Angular 2 apps
Programming with Mosh
34 Build a Real-world App with ASP.NET Core and Angular 2
Build a Real-world App with ASP.NET Core and Angular 2
Programming with Mosh
35 Entity Framework 6 Tutorial: Learn Entity Framework 6 from Scratch
Entity Framework 6 Tutorial: Learn Entity Framework 6 from Scratch
Programming with Mosh
36 Two-way Binding and ngModel in Angular 4
Two-way Binding and ngModel in Angular 4
Programming with Mosh
37 Udemy Live 2017: Teaching Tech Panel
Udemy Live 2017: Teaching Tech Panel
Programming with Mosh
38 Demo of An E-commerce App Built with Angular, Firebase and Bootstrap 4
Demo of An E-commerce App Built with Angular, Firebase and Bootstrap 4
Programming with Mosh
39 My Brand New Angular Course
My Brand New Angular Course
Programming with Mosh
40 TypeScript Tutorial - TypeScript for React - Learn TypeScript
TypeScript Tutorial - TypeScript for React - Learn TypeScript
Programming with Mosh
41 Access Modifiers in TypeScript
Access Modifiers in TypeScript
Programming with Mosh
42 TypeScript Interfaces
TypeScript Interfaces
Programming with Mosh
43 TypeScript Classes
TypeScript Classes
Programming with Mosh
44 TypeScript Constructors
TypeScript Constructors
Programming with Mosh
45 TypeScript Properties
TypeScript Properties
Programming with Mosh
46 Angular Tutorial for Beginners: Learn Angular & TypeScript
Angular Tutorial for Beginners: Learn Angular & TypeScript
Programming with Mosh
47 AngularJS vs Angular 2 vs Angular 4 | Mosh
AngularJS vs Angular 2 vs Angular 4 | Mosh
Programming with Mosh
48 Angular Material Tutorial | Mosh
Angular Material Tutorial | Mosh
Programming with Mosh
49 Angular Animations Tutorial | Mosh
Angular Animations Tutorial | Mosh
Programming with Mosh
50 Firebase in Angular Applications | Mosh
Firebase in Angular Applications | Mosh
Programming with Mosh
51 Deploying Angular Applications | Mosh
Deploying Angular Applications | Mosh
Programming with Mosh
52 Building Forms in Angular Apps | Mosh
Building Forms in Angular Apps | Mosh
Programming with Mosh
53 Directives in Angular Applications
Directives in Angular Applications
Programming with Mosh
54 Routing and Navigation in Angular | Mosh
Routing and Navigation in Angular | Mosh
Programming with Mosh
55 Angular 4 in 40 Minutes
Angular 4 in 40 Minutes
Programming with Mosh
56 [NEW COURSE] Unit Testing for C# Developers
[NEW COURSE] Unit Testing for C# Developers
Programming with Mosh
57 Unit Testing C# Code - Tutorial for Beginners
Unit Testing C# Code - Tutorial for Beginners
Programming with Mosh
58 C# Classes Tutorial | Mosh
C# Classes Tutorial | Mosh
Programming with Mosh
59 C# Object Initializers Tutorial
C# Object Initializers Tutorial
Programming with Mosh
60 C# Constructors Tutorial | Mosh
C# Constructors Tutorial | Mosh
Programming with Mosh

This video teaches how to use Redux in Angular 2+ apps, covering the basics of Redux, its benefits, and how to implement it in an Angular app. It also covers the concepts of state management, pure functions, and time travel debugging. By the end of this video, you will be able to design and implement a state management system using Redux in an Angular app.

Key Takeaways
  1. Build a Redux action with a type property
  2. Use a switch statement on the type property of the action to return a new state
  3. Return a new state with the updated property based on the action type
  4. Create a new folder for the Redux demo
  5. Run NG in the folder
  6. Install the latest version of angular CLI
  7. Install Redux and ng2 D rux
  8. Create a new angular project and add the dependencies
💡 Redux provides a powerful tool for time travel debugging, making it easier to test and debug the application.

Related AI Lessons

Up next
The masks we wear | Zora Krstić | TEDxLuxembourgCity
TEDx Talks
Watch →