Downloaded from git.ir
[Music]
so what is Redux Redux is a library that
helps you manage the state of your
application and is 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 complexity your application
so what do I mean by these large single
page applications well in a typical
angular app without the Redux archit
without the Redux architecture you know
that each component maintains the state
and the logic behind the view this model
aligns perfectly with the encapsulation
principle of object-oriented 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 this
situation we often have multiple copies
of the same data that are independent of
each other so whenever you update the
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 the passing data would be
simple it will simply use the input
properties of the child components to
pass the data down the subtree 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
to an event spaghetti in a large code
base we have events published all over
the place and then to track 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
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 space 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
provide a clean and elegant solution to
this problem maintaining the application
state in predictable way so there's no
surprises now apart from this Redux
provides a number of other benefits the
first one is that it decouples your
application 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
from Uncle Bob the second benefit is
that it makes it easier to test your
application without marks spice 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 take your
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 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 this
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
become really cut just like many other
architectural patterns you're going to
write a bit more code and you'll have
more moving parts in your application so
use redux only if you're building and
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
the 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 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 for
polling or push notifications so if you
have these scenarios in your application
it 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 state 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 slide 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 it
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 is ok to have a single
object to store the application States
the second piece is the actions actions
are playing javascript objects that we
present 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 the 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 an action can have
additional properties related to the
event
it just happens and the last piece
reducer the 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 it's 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 its
modifying its argument so if the value
of the count property of the input is
initially zero and we call this function
ten times to increment it instead of
getting one we get ten 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
back end calls by a disservice and this
is an example of a side effect so every
time we call this function our
application state store it in a database
on the server it's modified and here's
the third example in this function we
are updating the value of the count
property based on a random number
generated by the math class so with this
function if they 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 math dot random or data
now or any other functions that return a
different value every time we color now
let's take this first example and change
it to a pure function so instead of
incrementing this count property you
return a new object with accounts
property and the value of this count
property would be the value of the
original count plus 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 0 and we call this
function 10 times we'll get 1 because
this function 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
user functions always take two arguments
the current state and an action then
based on the action type they return a
new state so typically use a switch
statement on the type property of the
action and based on the value of the
type property we return a new state so
let's imagine action the type is
increment then we return a new state
with the updated property so you're not
going to modify the original state pass
the dysfunction 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 the
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 marks 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 state 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
dataflow for a calculator application he
doesn'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 its 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 implementations are mg RX / Store
and ng - - Redux these are the most
popular ones and they're very very
similar in terms of their API angel -
Redux is built on top of the real Redux
library and it's compatible with most of
the redux ecosystem
it adds bindings for angular 2 so you
can easily connect your angular
components with redux ng IX flash store
on the other hand has done the routes of
reimplemented the Redux pattern in an
angular 2 and rx friendly way this means
it's not compatible with other libraries
build for redux so in this section I'm
going to use ng 2 - redux but I wanted
you to be aware of ng RX / store because
there are a lot of blog posts and
questions on Stack Overflow that are
centered around this implementation
alright 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 1 beta 26 if yours
is older simply do NPM install angular -
CLI - JEE all right now I'm going to
create a new folder Redux - demo going
to this folder and run ng in it all
right now if you look at package that
JSON you'll notice that we're using
angular 2 point 3 point 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 point 3 point 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 n - 2 - 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 NGS serve
now if you head over to localhost 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 the TF here I'm going to
export an interface called a app state
so this interface determines the shape
of our store for now we're going to
leave it 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 route 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 the module on the top we need to
import a couple of types from ng to -
Redux so import from
ng to - 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 use or dependency
injection so ng Redux module now we want
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 going to go on the
top import I app state and route reducer
from current folder slash 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
injury Dex object here and call
configure store this is to initialize
our store now the first argument to this
method should be our route reducer so
route 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 you 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 is absolutely no errors
perfect so we have successfully
installed Redux in this project next
we're going to work with action all
right now let's see how we can use an
action so here in app component template
I'm going to add a button call it
increment
handle the colliculus and bind this to
the increment method of our components
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 add component stickler counter here
and initialize it to zero I'm going to
add the increment method so in a typical
angular app this is how we implement
this method you modify the state
directly here however when using the
Redux architecture we don't modify the
state here instead with dispatch and
action this action goes into the store
the store knows our route reducer so it
passes action to the route 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 this
first I'm going to go on top of this
file and import mg Redux from ng to -
Redux
so this is the primary type that the
worked 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 have
state on the top
like this
constructor I'm going to apply the
private modifier here so we can access
this in the increment method now instead
of modifying the state directly you're
going to call this that injury ducks
that's dispatch here we need to pass an
action object and as you learn 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
happen 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 every time we define a
new action we need to go to our reducer
and determine how the state will change
in response to the action so let's go to
the store here I'm going to add a switch
statement on action that type and it is
increment I'm going to return a new
state with updated counter so currently
it's not clear what is the type of this
data 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 AB 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 that 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 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 dispatch
an action then we went to our store we
modified the route reducer and added
support for the increment action then as
part of this we also have to modify I
app state so now we have this counter
property and finally in the app module
we modified 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 uses 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 extractives into one place define it
as a constant so this way we won't have
a type of 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
increments 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 at the 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 state here we had to go to
the app module and modify this initial
state object here so we are going back
and forth 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 a type I app state
and I'm going to set this so this object
would counter set to zero now time we're
going to modify the I app state
interface we could 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
vacation 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 Maha Madani and I'm a
full-stack developer applause I'd author
and in getting the instructor with about
14 courses at the time of recording this
video so I've got lots of courses on
both front end and back end development
including three sharp energy framework a
selectman MVC angular architecture unit
testing and so on
this video watch is actually part of my
angular course on udemy 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 with mass comm slash courses
you can also subscribe to my YouTube
channel to get free videos every week
have a great day and I'll be back show
[Music]