2,734,128 events, 1,223,664 push events, 2,016,570 commit messages, 156,197,745 characters
Updated htaccess
This fucking shit is so dumb I want to die fuck apache
sorry yue LOL
im stealing the bare bones of yuexr's page's bc. idk hwo to do that shit myself. and the license allows it. and its just like 4 divs anyways. thank you yue ur the Best
Give up on home-manager
Pros
- Everything managed with a single, real(ish) programming language is nice
- Nix is great for packaging and patching things exactly how you like
- Generations with rollbacks are cool (
home-manager
knows how to remove its old symlinks) - It was a good learning experience
Cons
- Config files are symlinks to immutable Nix store paths, and applying a new configuration is slow; the feedback loop sucks
- Configuring programs using Nix is cool, but there's too much "magic"; I don't know what options do, or how they're applied (some change the config file, others change a program wrapper, etc.)
tried to implement saving user shortcut tools BUT
hella bugs dude, fix it tomorrow jesus christ all hell broke loose after these changes lmao it's kinda funny ngl
Adds Not-Uno (#4387)
-
e
-
not uno
-
Fuck you travis
main menu. pause menu. jesus fucking christ why is SAVING THINGS SO FUCKING HARD HOLY SHIT AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
"8:45am. Am just chilling right now.
I got a good reply yesterday, and I know how to make those edits non-overlapping, but I am thinking whether I want to.
...Let me do my morning reading just for a bit and then I will start.
9:35am. Let me start. Unfortunately rather than working on blockization, I have another big post coming up in the issue 101744 on the VS Code repo.
Before I decide to take his advice and implement what he suggests, let me use my brain a little.
10:35am. Made that request. Now let me take a look at the slack. Got a reply on how to build VS Code.
///
ctrl+shift+B just runs the default build task so it will be whatever is set as default in the tasks.json
Is that supposed to be done from within the VS Code editor? Yeah, I've tried that, but I get an error right away.
I'll try yarn watchd
.
///
I get this.
///
e:\vscode>yarn watchd
yarn run v1.22.0
$ deemon yarn watch
'deemon' is not recognized as an internal or external command,
operable program or batch file.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Yeah, exit code 1 is what I get when I try to run the default build task in VS Code itself.
...Ok, so I installed deemon
globally via npm and then tried yarn watchd
again. This time it finished successfully, but did nothing.
E:\vscode>yarn watchd
yarn run v1.22.0
$ deemon yarn watch
$ concurrently "npm:watch-client" "npm:watch-extensions"
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Build daemon exited.
Done in 0.58s.
Ctrl+Shift+B from within VS Code is also doing visibly nothing, though I am not getting that exit code 1 error anymore. It is also doing nothing actually. I am guessing it is doing something similar to that yarn command and just finishes successfully under the hood without doing anything.
///
10:55am. https://github.com/microsoft/vscode/issues/ Tokenization overhaul
The issue 77140 here is interesting.
Ahhhh, once more tokenization ate up my morning. But I need to go through this. Maybe this won't be useful directly, but if I can spur the author to do a better job.
https://user-images.githubusercontent.com/5047891/62771189-eddf2700-ba9c-11e9-9263-604ad468deb2.png
Holy shit, this is what TS is using. I really hope this was not written by hand.
11:20am. They mention that one C++ regex is literally 20k lines. Now that is crazy.
Well, let me have a break here. I'll do it early today, so I can get back to work on blockization. I won't bother with the changes provider. I expect that I am going to get assent on my request to make the range provider faster. I want to resolve this flickering issue, but it is more important to me that this be done than for it to be done ASAP. The range provider is the most elegant solution, and since the changes one is acting strange, I might as well use my brain rather than do whatever just works.
I am really more concerned about not being able to support multiple passes due to the range provider not having a trigger.
But that will get resovled. I tried various paths, and decided to let myself fall into this here."
Fixes
- Fixed ace of clubs
- Made thorn stalkers not jump like idiots while casting
- Bloomshroom shouldnt be able to craft quivershroom in a bottle [Fixed]
- renamed floran ingot to floran bar [sorry yuyu, but it's about consistancy]
- Made the bubbles actually come OUT of the bubble blaster
- Elderbark Armoris now crafted at a crafting bench rather than an anvil
- Changed the value of the Elderbark Breastplate to 0
- Added 2 Enchanted Leaves to the recipes of the Elderbark Breastplate, 1 to the Elderbark Leggings and Helmet
- Made Marksman Boots: increase value to 7 Silver, increase recipe cost to 7 Old Leather
- Increased value of Marksmans Hood to 6 Silver, Increase recipe cost to 6 Old Leather
- Increased Value of Marksmans chestpiece to 8 Silver, Increase recipe cost to 8 old Leather
- Reduced Increased damage on bloodcourt vestments from 7% to 6% Winters Wake Rebalancing:
- Increased damage from 30 to 32
- Increased Critical Strike Chance from 4 to 8
- Renamed thorn hook to bramble hook
- removed pierce from sharpshooters glove
- increased range on longhorn blade -Increased range of magnet hook
example database update removes problematic quotes
good god, god's an evil devil? no?
- Mutations in Javascript 250. Equality of Arrays and Objects 251. A Misleading Rule(Section 19: Redux Store Design)
In this video we're going to move on to this last big rule around reducers.
This last one says must not mutate it's input states argument.
So just so you know the first argument that producers called with back on the song's application we
had called it the selected song or something like that.
But usually by convention we always refer to that first argument as state because that's what it really
is it is the piece of state that this reducer is managing from the last time that the producer ran.
So this rule right here says Do not mutate that first argument inside of your producer.
This rule is extremely misleading and possibly even a little bit wrong.
So in this video I want to first clarify exactly what it means to mutate something in the context of
the JavaScript language.
Well then take a brief pause.
We'll come back the next video and it will really start to examine what this rule means.
OK so what does mutate mean in the context of javascript.
I'm going to flip back over my application.
Notice I've got my Consul here.
I see a ton of air messaging that's totally fine on my console.
I'm going to click that little clear symbol right there and we're going to write out a little bit of
code to understand what mutations are inside of javascript.
I'm going to first begin by declaring a new array that I'm going to call colors and I'm going to put
in two strings into that thing red and green.
Now I can modify this array right here very easily by using a collection of different methods and different
pieces of syntax inside a javascript or example I could add in a new element to the end of the array
by calling colors push and then putting in a new string like so if I now print out that array colors
I'll see that it now has a new element inside of it.
Now this operation right here when we pushed a new element into the colors array is referred to as a
mutation.
We change the contents of the colors array.
Anytime that we change the contents of an array it is referred to as a mutation.
So I can take the form of adding an element of removing an element or by changing an element inside
there.
So let's take a look at another couple of ways that we could easily mutate an array.
I could say something like colorist dot pop and that will remove the last element inside there.
So now if I print out colors again I see that it's back to only having two elements.
That is a another type of mutation.
Now finally I could use my array accessor notation and select some particular element inside there and
say that I want to update that index with some new value like let's say think like so.
And now if I print out colors I see that the first element inside there have changed so that that is
three examples of mutating an array.
We have added a new element in we've removed an element and we have changed an element right here.
I just can see mutating an array is very very easy to do.
Chances are when you first learn Javascript these were some of the very first methods that you learnt
around arrays.
Now it's also take a look at how we can mutate a javascript object as well.
So I get to clear my console right here and then at the top I'm going to define a new object they'll
call profile and I'll say that this is an object that has a name property with the name of Alex.
Now just in a way that I can mutate an array.
I can also mutate an object very very easily as well.
A mutation on an object is anytime that we update the value of a property anytime that we add a key
value pair or anytime that we remove a key value pair.
So for example on an object I could say profile name equals Sam.
I have now mutated that object because I have changed a value inside of it by saying something like
profile.
I'll see that my new name is Sam.
I can also use say profile.
Age equals 30.
That is another mutation I have added a new key value pair to that object.
And so if I print out profile I can now see that the contents of the object had changed.
All rights that's mutations of a race and javascript objects in both cases it is extremely easy to mutate
values inside of javascript using the very basic syntax that you probably first learned when you started
learning javascript.
Now I want you to keep in mind right now that we are saying that we must not mutate that input argument
state.
So essentially that rule is saying we do not want to say anything.
Inside ever do sir we're can replace this code inside of here.
We do not want to do anything inside of your like state at zero equals Sam we do not want to do anything
like state push or semi-state pop.
We don't want to do anything like states or push and if we're working with an object we should not ever
do anything like state name equals Sam or state DOT.
Age equals 30.
In other words we are never going to write out state.
And then an equal sign to the right hand side like that we're never going to do that.
These are all bad things to do.
Oh they're bad.
All right.
Now as a quick side topic I want to mention it's mutation of strings and numbers inside a javascript.
It's going to flip back over here really quickly.
And I'm going to define a new variable here.
I'll say conc name is equal to Sam.
Now we can access individual characters inside of that name variable.
By using that familiar array accessor notation.
So I can say name at 0 and then print that out and I'll see that it is the first letter from that string
in this case capital S..
But if I try to change that value by saying name at zero equals capital X that code is going to run
successfully.
You'll see that there is no error message there.
There appears to be no problem whatsoever.
But if I then print out the name variable it is actually unchanged is still the original string.
Sam So inside of javascript strings and numbers are immutable values we can not change them in the same
way that we can easily change a array or an object.
And so if you have a producer that is always returning a number or a string you don't need to worry
about this mutation rule.
You only have to worry about these nutation things when you're working with an array or an object.
Now in practice our reducers most frequently are returning either a array or an object.
So this idea around mutation does come up pretty darn frequently.
OK so now that we understand what mutation means like in this rule right here.
Let's take a quick break.
When we come back in the next section we're going to really dive into this rule and understand exactly
what it's really trying to say because what you see here is not something that you take quite at face
value.
All right so quick pause and I'll see you in just a minute.
- Equality of Arrays and Objects
In last video we started talking about the fourth rule around reducers.
And we had added in a little bit more context to understanding exactly what the word mutate means in
javascript.
Now before you dive face first into this rule right.
One other quick side topic I just want to flip back over to my counsel over here very quickly.
One little thing I want to show you.
So inside of this little terminal I'm going to define a new array called numbers and I'll give it the
values 1 2 and 3.
Now you might know that inside of javascript we can very easily compare equality between two values
using the triple equals operator.
So for example I can say one equals equals equals 1 and that's going to return true.
Likewise I can do a string of high.
Equals equals equals high.
And that would turn true as well.
And of course if I do one not equals two we're gonna get True.
And 1 not equals 1 is going to be false because 1 and 1 are equal to each other.
Now this comparison operator can be used on arrays in objects as well.
So I can very easily say something like Does numbers equal or equal equal numbers like so and of course
that is true.
Now in the case of primitive values such as numbers and strings we can kind of imagine that this is
a value comparison.
In other words is the number one equal to the value of the number 1.
But how comparison is done around arrays and objects is a little bit more subtle.
You see when you use this triplet equals operator right here on an array javascript is checking to see
if it is a reference to the exact same array in memory not the contents of the array.
So for example if I say numbers numbers numbers equals a brand new array of 1 to 3 this is going to
return false because the comparison here is not between the contents of the array.
You'll notice those are identical.
The comparison is between whether or not numbers.
This variable right here is referencing the exact same array in memory as the one on the right hand
side this one over here.
In this case it is not.
We declared this array up here that is in some location in memory or RAM on your computer and then you
defined a completely new array down here.
So you now have two separate arrays inside of RAM or memory on your computer.
And so in this case these two separate arrays are clearly not the same array.
So when we do this comparison it's going to return a value false because no it's not the same array
in memory OK.
Now we understand that.
Let's take one more very brief pause.
I promised last pause here and then we come back we'll finish up on this rule.
- A Misleading Rule
In the last two videos I've kind of directed away from this last rule right here.
I don't think I can do that anymore.
So let's just get down to it.
Let's talk about what this rule is really talking about.
All right so must not mutate the state argument.
Here's the thing.
This rule is extremely misleading is extremely misleading and possibly even false.
So you might be curious Steven why did you put a misleading or a false rule on this list of rules around
reducers.
Well the reason that I put this rule on here is that you're going to see a tremendous number of blog
posts tutorials and articles even documentation that all give these exact words right here.
All these other people are going to say to you do not mutate that state argument.
But here's the truth.
Let me get it.
I'm going to give you the truth right now.
The truth is you can mutate that state argument all day.
You can add in elements to a you can remove elements you can change elements you can add in properties
to objects you can change properties on objects all on that state's argument.
And you know what.
Redux is never going to give you any error message when you do so.
So all the bad code that we wrote inside this producer right here you can absolutely run this and redux
is not going to throw any error message at you.
But clearly people tell you this rule for a reason.
So why is that why do people say that you must not mutate the state argument.
Well to be honest it really comes down to this right here.
You can mutate that state argument but there is one tiny little corner case in which mutating the state
argument is going to land you in trouble.
There's one tiny little corner case where if you meet that state argument your application is not going
to work the way you expect and to be honest it's a lot easier to tell beginners to just not mutate the
state argument than to tell them about this corner case and help them understand when that corner case
applies.
So in this video I'm going to tell you exactly what that corner case is we're going to get a better
understanding of why people say you must not mutate that state argument.
Right now one thing and do very quickly just to clarify I want to be very clear right now.
You and I are never going to mutate the state argument ever.
You can.
You absolutely can.
And I'm going to show you this corner case and help you really understand this rule.
But we are not going to mutate the state argument ever.
The reason that I am showing you this rule and going so far into detail is that I want to help you understand
the behind the scenes stuff that is going on inside of redux.
But best practice the convention is to not mutate that state argument.
And we are going to stick with that convention.
OK.
So we're not going to take state.
I just want you to better understand what is going on here.
All right.
So let's get to it.
To better understand this rule we're going to take a look at the source code of the redux library itself.
This is a link to the get hub repository that houses all of the source code for redux.
We're going to dive through that source code.
We're going to find one very specific chunk of code and using that knowledge that we just gained around
mutating arrays and objects and doing identity comparisons on Rayson objects.
We're going to get a better idea of exactly what that rule is talking about.
All right so going to copy this link I'm going to pull open a new tab and navigate over there.
So here's the good hub repository with all of the source code for the ducks.
We're going to scroll down a little bit and find the sarcy directory.
So SIRC been inside of this SIRC folder.
You're going to see a couple of very familiar names sirrahs apply middleware yours combined reducers
and here is create store.
We're going to open up the combined reducers thunked file and then inside of combined reducers we're
going to scroll down to the very bottom.
Now as you are looking at this file at some point in time in the future some of the different coding
numbers that you see on the left hand side are a line code lines excuse me are going to be maybe a little
bit changed versus what I'm looking for.
So essentially what we are looking for is something around line 162 we are looking for a variable called
has changed.
So this block of code right here is what we're going to study to really understand what that rule is
talking about this chunk of code see right here is the code that is going to take an action.
Anytime that it gets dispatched and send the action around to all the different reducers inside of your
application.
So in other words every time you dispatch an action this code right here is going to be executed.
So we're going to walk to this code step by step and get a better idea of what happens when you dispatch
an action.
All right.
Notice the first thing that happens is we set up a variable called has changed and equal said equal
to false.
This is a really key variable.
We're going to come back and talk about it in just a little bit.
I just want to point it out.
For right now then on line 164 you'll notice that we enter a for loop.
This for loop is going to iterate over all the different reducers inside of your application.
So at present inside of our index dot J has filed and in the reducers directory We only have one reducer.
But if we had some other reducers inside of here like you know maybe 5 or so something like that that
for a loop is going to iterate over each of these different reduce or functions
then inside the body of the for loop.
Take a look at line 167.
We're looking for a variable right.
You're called previous state for key this variable right here is going to be assigned the last state
value that are reduced or returned.
So remember we just spoke about this every single time that every or gets called The first argument
is going to be the state that returned the last time it had ran.
So essentially this previous state for key is a reference to the previous state value that this particular
reducer that we are iterating over returned.
Then on the next line 168 right here this is the real magic.
This is where we actually invoke your reducer so that reduce or variable right there that is your reducer
that you pass to the combined reducers function.
The first argument is the state that you reduce or return the last time that it ran previous state for
key and then the second argument is the action object.
So your douceur is going to run and then it's going to eventually return some new value some new state
value and that's going to be assigned to next state for key.
So we now have has changed.
We have previous state for Kii which is our last state value and next state for key which is our new
state value.
Immediately after your reduce or runs and assigns that new state value to next save for key redux is
going to check to see if you're reduced or just returned a value of undefined.
That's what this statement right here does.
Remember that was one of our big rules around reducers we had said that a producer can never return
a value of undefined.
And you're seeing that check right here in action.
Redux says OK did they just returned the value undefined.
If they did We're going to throw a new error message.
Now assuming that you get past that check go down to line 174 and here's where things start to get really
really interesting.
So we're going to again look at that has changed value.
Has changed is going to take the value of a direct comparison between next state for me and your previous
state for key.
This is that rule that we're talking about the do not mutate state.
This is what it all comes down to right here to take a look at what this comparison does.
Remember we just spoke about what the not equals equals.
Operator does this checks to see if next state for key and previous state for key are the exact same
array or object in memory.
So if you just returned some array and it is the exact same array in memory that you returned the last
time that this producer ran then has change is going to be a value of false otherwise otherwise if you
reduce or just ran and it just returned a brand new array completely brand new just created inside of
your reducer.
And this is a totally different array than the one that your reducer ran to me returned the last time
it ran then has changed is going to be set equal to true so this has change variable.
Essentially saying has any of the state returned by or reduced or changed.
That is what the name has changed is referring to it as saying we have just dispatch in action.
Has any of the state produced by reducers changed in any way.
So the for loop is going to iterate over all of your reducers and then has changed.
It's going to be either true or false.
Considering all of those different reducers.
Notice how there is only one has changed variable right here.
There is not a separate house change variable for each producer If any different reducer has changed
value or returned a new value a new array or a new object or a different value for an integer or a number
or a string has changed is going to be set equal to true.
So it's kind of a all or nothing deal.
And then after the for loop here's where things get really really interesting.
We then look at the value of how it's changed if has changed is equal to true the result of this entire
function is to return the new state object like the entire new state object that has been assembled
by all of your different reduces otherwise if has changed is equal to false instead return state and
state right here is a reference to all the state that you're reducers returned the last time that they
ran.
So to sum up this code block right here in very simple terms.
Essentially what this does is check to see after running each of your reducers if any reduce or returns
a brand new Array object or value for a number or string.
If they do then redux is going to return the brand new result from all of your reducers.
Otherwise if you're reducers returned no new value it's going to return the old states where the old
result from each of your reducers.
Now why is that relevant.
The reason this is relevant is that if redux returns the old state value right here then redux is not
going to notify the rest of your application that any of your data has changed.
If you do have a new state.
If you have changed something from one of your producers and you instead return next state right here
redux is going to look at that object.
It's going to say oh we just got some new states some new state just came out of all of our different
reducers and it's then going to notify the rest of your application including your re-act application
that you have a new state available and that is going to cause your re-act application to re render.
So in summary the reason we care so much about saying that you must not mutate at state argument is
not because you can't mutate the state argument.
That's not the case.
The reason we say this is that if you accidentally return the same value that is pumped into your reducer
like even if you change it even if we modify this thing right here if we eventually say return state
at the very bottom and it's still the same object or the same array be it modified or not.
Redux is going to say oh no difference here is the same object or array in memory.
Nothing has changed.
And so we have done absolutely no updates to any data inside of our application.
And the re-act up does not need to be rendered itself.
And so you will never see any updated content appear on the screen.
That is what is actually going on here.
And that is what this rule right here is really trying to convey.
This rule is really trying to tell you if you return the state argument right here making changes to
it or not making changes to it.
It doesn't matter if you return the same value at the very bottom then no update will be made to your
application and that's it.
That is what people are trying to convey with this real right here.
That is why people say do not mutate these state arguments.
Now as you might imagine it's a lot easier to just tell people do not mutate the state argument than
to go through the description or the entire process that I just gave you.
So that's why it's a lot easier for when you're first learning redux.
Just understand don't mutate the state argument than to actually understand all the behind the scenes
stuff that's going on.
OK.
So that's it.
That's rule number for around reducers.
We've now gone through a whole four rules right here.
Now to take a quick pause.
When we come back the next section I'm going to tell you how we are going to generally handle arrays
and objects inside of reducer so we can handle this rule appropriately and make sure that if we do want
to make a change to the state argument we don't do so in a way that is friendly and familiar to redux.
So quick pause and I'll see you in just a minute.
- Extracting Logic to MapStateToProps 261. That's the Issue!(Section 19: Redux Store Design)
In the last video we got our application working.
But there's one quick little improvement.
I want to make to our user Hetter a component.
Now this is a very small thing and it's going to appear really small in this case but it's something
that over time as you start to work on more complicated applications is going to become more and more
useful.
All right so let me show you what it is inside of our user head or component.
We are passing this thing a collection of different props.
Right now this thing gets access to the user ID and it also gets access to the entire list of users.
Now I want to point out something here really quickly.
The user Hetrick component is not really well-suited to take the entire array of users.
That might sound like a really weird thing to say but essentially the entire purpose of the user Hetter
component is to show one singular user on the screen.
It only has to show one user but we're giving it way more data than it ever needs we are giving it the
entire list of users.
And so to make this component by itself like just this class right here a little bit more reusable I
think that it would be a lot better if we could figure out some way to pass it.
Just the user that it cares about like maybe the ID that it cares about and the user that it cares about
but definitely not the big array.
So to do so there's a couple of different approaches we could take we could either get our entire list
of users inside of Post's list and then every single time that we render the user had a right year we
could go through that find logic and attempt to just pass in the user that we care about as opposed
to this user ID.
But I want to show you one other approach that we could take.
Back inside of my user head or component I'm going to go down to the map state to prop's function.
All right mount stage props right here.
Now you might notice that this map state to prop's function seems just like a little bit unnecessary.
Right.
Like every time we want to pull some data out of a component we have to define this really repetitive
function and then have to build up this object right here.
That gets some data out of our store.
Another way that would have been really nice to pull data out did the redux store then have to define
this whole function.
You can't do this to be clear.
You can't do this what I'm about to show you is not valid but it would have been nice if we could just
like pass in a string of something like.
Users like so and then just say that connect should understand that we want to pull the user's property
off the state object and pass it into our component as a prop called users.
Right.
That would have been kind of cool if we could have just done that but instead we have to go through
this really long definition of map state to prop's So it turns out that there's actually kind of a reason
for that.
The reason that we defined map states right here is so that we can do kind of like these pre calculations
on values that are coming into our phone as props and our redux state.
So rather than passing in like a ton of data to our component and relying upon the component to figure
out how to find the user that we care about we could instead extract all that logic to the map state
to prop's function.
So rather than going through this find operation inside the components self right that logic out inside
of map state to.
Now like I said that probably sounds like a very very small distinction.
You know I just told you two seconds ago.
Yeah you know it be nice to make this component more usable and it would be more reusable if we did
not have to pass that the entire list of users.
But then as the solution.
I'm saying that we're basically just going to relocate that logic to a couple lines down inside this
file.
So it might sound like that's no increase in re-usability at all.
Well let me tell you why this kind of technically is an increase in reusability.
It turns out that in some applications like some professional applications some engineers decide to
define this map state to proper function and this stuff right here inside of a separate file.
So you might have one file that has mapped state to props and the initial connect set up right here
and then in a different file you will define the component by itself.
The advantage to that is that you will have a component that can be used on its own without having to
reach into the redux store by going through all this work right here.
But then if you want to you can also very easily create a version of that component that will reach
into the redux store and get all of its own data.
In addition if you ever have another component that needs to get access to say just one particular user
given only a user ID we could easily write map state to props and this connect stuff into a separate
file and then reuse it in multiple components inside of our application.
So like I said it probably doesn't seem like this is going to be any increase in reusability of our
component but in the long run in some applications you're going to find that this is kind of a common
pattern to extract a lot of logic into map stage props.
OK.
So enough talking.
I think you probably get the idea.
So essentially rather than finding the appropriate user inside of our component we want to find the
appropriate user inside of map stage props.
So to do so I'm going to remove this fine statement right here entirely.
We're going to replace it in just a second and we're going to instead place the find statement inside
of Mount St. to.
So I will say St..
Users find and then for every user inside there I want to look at the user id and compare it to oh wait
oh that's a little bit of an issue.
Right here we want to find a user ID that is equal to this component's prop of user ID but that Propp
is only available inside that component.
We can't get access to it inside a map stage props or can we.
Well it turns out we can.
So maps to prop's does not only get cold with our state object out of our redux store as an argument
it actually gets a second argument as well that is referred to as own props this own props object right
here is a copy not actually a copy is a reference to the props that are about to be sent into this component
right here.
So if we ever want to do some of these like pre calculation steps so that we don't have to pass in a
ton of data directly to the components we can reference the props that are about to go into the components
on this object right here.
And then we get our redux state on the first argument.
So essentially we're going to compare user ID with own props dots user id like so and that's pretty
much it.
Well actually just a little bit more that's going to find the appropriate user.
We don't really want to assign that to a property called users anymore.
We probably want to assign that to a property called user.
So we'll update that.
And then finally inside my render method we no longer have access to the Propst users value.
Instead it's simply this stop Propst users Cingular because now we are only passing on the one user
that we care about to our components.
So instead of my render method I'm going to do structure off just that user from my prop's object.
And so now we can check to see if that user exists.
If they don't we'll return NULL and show nothing on the screen.
But if they do we'll show their name inside that div OK.
So again the entire idea here is that we can extract anything that is going to do some computation on
our state our redux States and the prop's coming into our component to the map states prop's function.
And that's really what map state to props is for.
All right so let's save this and then we'll test it out really quickly and just make sure that everything
still works and it looks like yes it does.
I still see all my authors on here.
OK.
So that's a good refactor.
Now I'll take a quick pause right here.
When we come back the next section.
Remember I'd said very mysteriously that there's still a little bit of a problem inside of her.
So let's take a quick pause come back the next video and I'll show you exactly what that problem is.
- That's the Issue!
In the last couple of videos I've mentioned that there is a little problem with our application.
And so in this video and it tell you exactly what that problem is and then will start to take a look
at two different ways of solving that problem.
All right so I'm going to open up my chrome Council right here.
I'm going to find the network request tab and then I'm going to make sure that I'm filtering by x h
our requests.
Once I have that all selected and then going to it refreshed the page and we're going to take a look
at the request that are being issued by our application.
All right.
So take a look at this at the very top.
We've got our request to the post and point.
And then after that we've got a request to get users slash 1.
That means that we're getting the user ID number one and then the next request is also user with ID
And then also user ID 1 and so on we are making request for user ID number one 10 times in a row and
then we are doing the same thing with user ID number 2 and 3 and 4 and so on.
In total we are making a hundred separate requests to fetch just 10 individual users.
So what's going wrong here.
Well remember we are showing one instance of the user Hetter component for every single blog post that
we fetch every time that a user header is rendered on the screen component amount is called in and so
we call this action creator fecche user with this particular user ID.
So essentially because we are rendering out a hundred instances of user Hetter our action creator gets
called a hundred different times.
Even though we are fetching some very very repetitive data.
So thats the issue we are fetching these users 10 times more often or frequently than we actually have
to.
Ideally we would only fetch each one of these user users exactly one time.
So we are going to have to figure out some way to make sure that we dont make all these duplicate requests
for each individual user.
So thats the big challenge and that's what's wrong with our application right now.
Now like I mentioned we're going to take a look at two different ways of solving this problem.
Now there's kind of a I don't know kind of easy way and kind of the easy way I would not necessarily
say that one method is significantly easier than the other.
One way is just a tiny little code change that we're going to make but it involves some really crazy
syntax.
The other way is a much more complicated change but it's also much easier to understand what is going
on and also take a pause right here.
When we come back the next section we're going to try solving this problem using the quick code change
that is kind of challenging to understand the syntax I'm making way too much of this list is take a
pause like the change in the next video.
So see you in just a minute.
- Displaying Users 257. Fetching Singular Records(Section 19: Redux Store Design)
In this video we're going to start thinking about putting together the user Hetter component to be precise.
We're not going to work on the component just yet.
Instead we're going to focus on making sure that we have loaded up the data that we need to show the
user header.
Now that might sound confusing.
So let me give you a quick reminder on how this API is structured.
All right.
Here's the documentation for the API we're using.
Remember it's that Jaison placeholder Dom Type-I Cocom.
I'm looking at the resources section.
At present we are loading up this list of posts into our application so our app is currently showing
a 100 different blog posts on the screen.
We can open up that in point and we can see all the data that our application is currently retrieving.
All right here we go.
So we have this list of blog post we have a body.
We have a title.
We have the ID of each blog post.
And then very important for what we are trying to do right now we have the ID of the user who made this
blog post.
So this post right here was made by the user with I-T one and the same thing at the next post and the
next post and so on.
Every ten posts inside of here has been made by a different user.
So if I scroll down 10 posts I'll see that I now move onto the next user the user with ID number two.
And then we can keep on going down down down down.
Eventually we'll see that we get to user with I-T 10.
So all of the blog posts that we have retrieved are made by user 1 2 3 4 5 6 7 8 9 or 10.
So to figure out the details about each of those users we are going to have to make an additional API
request if you go back over to this Resources section right here you'll see the users and point.
So we can open up that request and you'll see that this endpoint has 10 different users.
So user with 81 82 and all the way down to I-T 10 down here.
So essentially if we want to show the actual name of the author of that post inside this user Hetter
component for every blog post we are going to have to make a follow up request to the user's endpoint.
Get that list of users and that will tell us essentially who made which blog post and Lookout's and
other we understand the problem here.
I want to tell you there is kind of an easy way to do this and there is a hard way to do it.
So the first show you the easy way because unfortunately for us we're going to do it the hard way so
easy way first.
All right so a quick diagram.
I put this diagram together here just to make sure it's really clear how the list of posts related to
each user but I think you probably understand that relationship so we'll just get that diagram.
OK so we know that we have the entire list of posts and we know that that users endpoint will return
us every user that exists inside of this kind of little mini application.
In other words if we make a request to posts and a second request to the user's endpoint we're going
to have without a doubt all of the application or all seem to all the data that our application needs.
Now here's the problem that's like way too easy.
This is a little sample application to help you learn things.
Nonetheless just getting that entire list of users from the get go is just entirely too easy.
Let me tell you why that's too easy.
I want you to think about a real blogging application like say medium dotcom if you've ever been over
there medium Dotcom has like millions of blog posts.
Millions of users if they want to show a list of blog posts along with their authors to the user or
to a user as we are doing right now the medium people you know the engineers are not going to send your
browser a list of like a million blog posts and a million users.
Instead they're going to send you like 10 blog posts to show on the screen or something like that.
And then you'll have to make a follow up request for each of those individual users.
So if we just made the request for all the users that we would ever need it's just too easy and it's
not realistic.
That is not how you're going to see things done in a real application.
So instead we're going to do things kind of like a hard way.
All right.
Just a little bit more challenging.
If you go back over to the documentation over here under the resources section you can see there is
routes right here.
So take a look at the second route.
What this is essentially telling us is that we can make requests to get one individual record at a time
as opposed to these big gigantic lists of records that we've been taking a look at.
So for example if I wanted to only get the user with I.T. one I could change the you are you are l appear
from slash users to users slash 1.
So that means as you might guess give me the user with the ID of one.
And so when I go there I see just the first user on the screen and I can do user at 32 and so on all
the way up to user ID 10 like so.
So with that in mind here's the flow that you and I are going to go through.
All right.
So inside of application everything is going to start off with us fetching that list appose.
So we're going to make an API request.
And then after some period of time indicated by this little arrow right here we're going to get a response.
We're going to return that data from producer.
All that stuff and then eventually we're going to show our lists opposed to the user inside that post
list component.
Now inside of that render list method that we have inside there we're going to create a separate instance
of the user header component for every individual post.
In other words if we go back over to the render list method right here this map function right here
or the inner function I should say is going to be executed a hundred times because we have a hundred
different posts.
So somewhere inside if you're like let's say right here we're going to place our user Hetter component
and we're going to give it a prop of something like user ID and inside of you will put whatever this
particular user's ideas for this particular blog post be it like one or two or three or four or ten
whatever it is.
And so we're going to create a bunch of instances of the user header component and each one is going
to know exactly what Id user ID needs to show on the screen.
Now I'm going to clean this code up I just want to give you a quick example.
So then inside of the user header component we're going to add a call to a new action creator that's
going to attempt to fetch just the individual user that that instance of the user header needs.
So we're going to end up with a bunch of separate requests for each individual user.
So this would be like fetch a user id one.
This would be like ID too and ID 3 and so on and so we're going to make 10 separate requests.
In theory one for each user will get each user return it back to our application somehow process that
through a reducer and somehow get each relevant user into each instance of the user Hetter component.
All right.
So thats the idea essentially the idea here just to sum up is that if we just fetch the entire list
of users that is too easy and the real world does not work like that youre not going to get this like
nice and point this is going to give you a list of every record that you need in the real world instead.
Its way more common to do some initial request to get like a list of records and then you have to make
a bunch of individual follow up requests to get more information about each of the original records.
And so that's that's is exactly what we want to do.
We want to get the big list and then make some smaller requests to follow up on it and get just the
information we need.
Okay.
So along the way we're going to see a lot of fun.
We're going to encounter one or two kind of catastrophic problems but hey that's where the learning
actually kicks in.
So anyway let's take a quick pause right here and we're going to start putting all the solutions together
in the next video.
- Fetching Singular Records
In the last video we spoke about exactly how we're going to load up our users into our application.
So we're not going to take the easy way out.
We're going to do things the more realistic albeit a little bit more challenging way.
And like I said I can tell you right now we are going to run into one or two issues.
So if at some point something looks a little bit off don't sweat it we're probably going to end up fixing
it.
All right.
So here's the idea.
We're going to create a new action creator called fetch user.
Now remember our current action creator is called fetch posts and there's that s on the end which indicates
we are fetching multiple posts from one action Creator.
This new action creators called fetch user singular and so the idea here is that we're going to use
the action creator to fetch one individual user at a time.
Now the action crater itself it's going to make a request over to that API.
It's going to get our chosen user like some user with some particular ID and then it will dispatch an
action with the type of something like fecche user and will have our data on the pallet property.
Remember we don't really want to use just the response that I typed on here it's actually response data
that we care about.
So then we're going to also create a user's reducer which is going to hold a list of all of the users
we have into our application.
So notice how the action creator is fetching one record.
But we're going to essentially tabulate or collect all the different records that we get inside of that
reducer.
OK.
Let's get to it.
I'm going to flip back over to my code editor.
We're going to first start off inside of our actions index indexed Yes file by putting together a new
action creator to fetch just one user at a time.
So the actual creator we're going to put together is going to initially look basically identical to
the one that we have right here.
So I'm going to say export Konst fetch user when we call this action creator we're going to pass in
the idea of the user that we want to fetch as an argument.
So this idea right here this is going to be the idea of the user that we want to fetch.
So then we're going to use the same format where we have a function that returns a function.
So I will say async dispatch
and then we'll say Konst response is going to be a wait.
Jason plays older.
Don't get in now this time we are not going to make a request to the posts and point.
Instead we want to make requests to the users and point but we want to fetch a user with this very particular
ID.
And remember as I showed you in the last video we can fetch one individual user at a time by putting
a slash and then the idea of the user that we want to fetch.
So over here we're not going to put just users of what we really want is users slash.
Id like so we're going to rewrite that using yes 20:15 syntax with a template string instead.
Just to kind of clean up a little bit.
So I'm going to replace the single quotes with back ticks like so and I'll put my dollar sign curly
braces ID inside there.
All right so after we make that request and get back a response I'll then dispatch an action with type
batch underscore user.
And again remember it is singular.
No æsir because we are fetching one user at a time and then on our Paillard property we will put response
dot data.
All right so that's pretty much it.
Now one thing I want to point out here is that in fetch posts where we fetch a list of posts the response
that we got was a array of records.
So notice how.
Here's the Post's end point we got back an array of objects but when we fetch one user at a time we
don't get an array we get just an object that has details about that given user.
So just something I want to point out because that's going to end up in are reduced to looking like
ever so slightly different.
Maybe we will see.
OK.
So this looks good.
We've got our action creator put together.
So let's take a quick pause right here.
When we come back in the next section we're going to start putting together our user Hetter component
and making sure that it can call Fettes user right here at the appropriate time.
So a quick pause and I'll see you in just a minute.
263.2. Memoization Issues(Section 19: Redux Store Design)
I'm not going to flip on over to my code editor and I'm going to open up my action creators file.
So in spite of actions index yes I'll first begin by importing the load Eshe library up at the top like
so now.
Usually by convention we import the ash library as the underscore character.
Rather than calling it so like load ash or something like that.
All right.
Now we can use load ashed to memorize our action creator but just one quick pause remember in the start
of the last video I had told you that this solution was going to involve changing just a couple of lines
of code but it was also going to involve some really nasty syntax so unfortunately we cannot just kind
of memorize this fetch user function and expect everything to work as expected.
Instead it's going to be just a little bit challenging.
Let me show you why we're going to try to apply the memoires function to our action creator right here
and you're going to very quickly see that things are not quite working as you might expect now to apply
them wise to this thing.
I'm going to first rewrite it using the function keywords as opposed to erro functions just so that
it's really clear in the syntax exactly what is going on.
So I'm going to copy that user action creator and then I'm going to comment out the original one for
just a moment we're going to use this code again in just a moment but I want to re factor this thing
to use the function keyword as opposed to era functions just to make this more clear.
All right so now I'm going to put a new line right after async dispatch right here and I'm going to
turn this into a normal keyword function by putting in the function keyword removing that arrow right
there and then I'll put in a new clearly brace after the dispatch like so.
So right there normal function keyword.
Now I'm going to do the same process on the arrow function up here.
I'll change it to a function that gets called with ID and an opening Crilley Berrys like so now at this
point I would encourage you to do a quick save and make sure that you don't see any error messages like
the one that I have right here.
So let's figure out what's going wrong right here.
See I need to return that thing for sure.
And then I must have some other typo inside of me.
That's better I guess.
Make sure that you've got no ears inside of your browser.
Now once you've got that all set up well then attempt to memorize one of these two functions.
So notice how there really are two functions here.
There's the outer function and the inner one.
So the question is which one are we going to actually memorize.
Well let's just take a guess here and try to memorize the outer function first.
So I'm going to say underscore Mentawai is a place my print the C and I'll place the closing parentheses
around the entire function like so down here on the bottom line.
So now let's save this and see if it solves our problem.
Remember in theory now we are going to assign a memorized version of this function to the Fettes user
and export it from this file.
And so in theory we should only ever be allowed to call this function with a unique argument one time
and after that one time will then just return whatever the previous return value was.
So again you might be expecting that this would solve the problem.
All right so let's save this.
Flip back over and you're going to very quickly see that we're still making a ton of different requests
here.
So what's going on.
Well actually this is kind of playing out with memoires exactly as you really would expect if you think
about it every single time that we call this function right here.
It's going to return whatever was returned the first time it was called.
In this case it is a function.
We are returning this function right here every single time it gets called.
Even though it is memorized because that is the purpose of memoization we're not technically rerunning
this code right here.
We're not running the function again with the given ID.
But we are returning the same function that was returned the first time because we returned that function
Reducto thunk is still going to invoke that function.
So redux thunk is still going to call this thing right here.
Right with dispatch.
And inside of there we're still going to make our network request.
So unfortunately this is kind of expected behavior of nebulized but it doesn't quite do exactly what
we wanted.
- Dispatching Correct Values(Section 19: Redux Store Design)
Unless video we fix up our posts reducer.
So now any time that we make a request over to that API we should be getting back in action with our
Paller properties showing up inside the reducer that reduce search should be returning the list of posts.
So our redux state object is now going to contain that list of blog posts from the API as soon as that
happens our entire read re-act application should be rendered.
It's not the last thing we do is open up that component of post list.
It is right here and we need to make sure that we get that list of posts inside this component.
Remember anytime we want to get some data from the redux side of our application into the Riak side
we're always going to define the map state to prop's function and pass it off to you connect.
Down here at the bottom.
So underneath my component I'm going to define map state to prop's.
This is going to be called with our entire state object out at the redux store.
If you open up your reducers index file you'll recall that we assigned our reducer to this post key
inside of our combined reducers call.
So that means that our state object right here is going to have a property called posts and that property
is going to hold all the data that are douceur has returned.
So inside a map state the props are going to return an object with posts and it's gonna have the value
of status posts
and then going to take map state to props and hand it off as the first argument to the connect function.
All right so now every single time that our reducers run map state to prop's is going to be called again.
We're going to return a new object with property posts and that object is going to show up as the prop's
object inside of our component.
So now just to test to make sure everything is working OK.
I'm going to add a console log to my render method and I'm going to cancel log out this prop's posts.
Now one thing I ought to mention very quickly before we test this we technically have one little air
inside of our code present that air that we have is not going to result in any error message.
I left this error this error in or little mistake and because I want you to see exactly what happens
when this error is in.
I really expect this is going to be an error that you're going to make.
Unfortunately when you start working on your own project so I just want you to see this air firsthand.
OK.
So we're going to save this and we'll flip back over to our application and we'll see that inside of
our council.
We have two council statements here now.
First off why do we have to cancel logs.
The reason we have two council locks is that when our application is first loaded up inside the browser.
All of our producers run one initial time so the instant our application loads up inside the browser
are reduced to right here runs it's going to run with an action of some initialization type it's going
to have some random type inside of that action object whatever type it is.
It's probably not going to match the case that we have right here of fetch posts.
So we're going to return our default state value of an empty array.
So when our application first boots up we're going to have a state object that has a post property and
that post property is going to contain this empty array.
After all of our producers run our application the Riak side of application is going to be rendered
one time on the screen.
So the post list component is going to be displayed on the screen one time during that initial one time.
We're going to have our render method called and that's going to invoke the console log right here.
And so we see a single console log with this Propst outposts that is this empty array that you see right
here.
So that is the initial first time our application is rendered onto the screen.
Now immediately after the postals component shows up on the screen our component did mount lifecycle
method will be called and then we go through that entire process of running off to that API and fetching
some data after we get some back some data and we dispatch a action to reduce her or reduce or sees
that the action has a type of post it returns whatever value is inside of that action at Paller property
redux sees that we have not returned the same object in memory.
We have not returned that same array.
The second time we do Saran Instead we return this brand new value.
This action not payload whatever it is because that is a totally new value redux assumes that it has
some new data inside of our application and redux essentially tells react to revenger itself.
With this new data and so our post last component is going to be rendered to the screen a second time
map states prop's is going to be called a second time.
We're not going to get the new value of states posts and then that new prop's property or prop's post
is going to show up inside of our component the render method gets called again and we see that console
log a second time appear.
OK so that's a long winded explanation of why we have to console.
And the first console log is an array.
Which is exactly what we want.
Because that is our default state value.
But then the second console log this is where that little air I mentioned comes into play.
So you'll notice that the console like here for this Propst up posts is the entire response object that
we got back from the API or through Acciona essentially.
And so this object has properties like config and headers and request we don't care about any of those
properties whatsoever.
The only thing that we care about in that response is the data right here.
That is the list of blog posts that we are trying to show on the screen.
And so the little air that we have inside of our code right now is essentially just the fact that we
are dispatching the entire response object from our action creator when in fact we should probably only
be dispatching this data array instead.
So essentially back inside of my actions file here's where we dispatch our action.
And on our Paillard property we have that entire response.
So we don't care about the entire response.
All you and I really care about and the only thing we really want to be picked up by our reducer is
the data property on there.
So I get to make sure I put response data like so so now that I've got response data that means that
when we get that second console log we should see the array of posts that are now showing up as props
inside the post list component.
So if we flip back over after saving we'll see the first console log of empty array and we'll see second
counts alog with our list of posts inside of it.
Perfect.
OK.
So now that we've got the list of posts list of posts here we can now take a quick pause and when we
come back we're going to add some more logic to our post list component and make sure that we render
out that list of posts as a list on the screen.
So quick break and I'll see you in just a minute.
- List Building! (Section 19: Redux Store Design)
Now that we've got our list of posts inside of our post list component we can start to display these
things on the screen.
All right.
I'm going to take a second method or third method I suppose inside of my class.
This is going to be called render a list.
And as you might imagine I'm going to stuff a ton of logic into this thing to take my list of posts
and render them out.
I'm putting all this logic into this helper method of render list just to keep the render method itself
nice and easy to read.
So inside of render list I'm going to return this stuff prop stock posts.
I'm going to map over it and for every post we are going to return a pretty good blob of GSX.
Now as a quick reminder we're making use of semantic UI here.
So on the GSX block we're about to write out.
I'm going to add in a pretty good amount of class names in all these class names are just references
to semantic UI and just trying to get stuff to appear on the screen and look pretty nice.
So I'm going to return a div with the class name of item.
I'm going to remember to give this thing a key property.
Remember that every post that we fetch from that from that API has an ID associated with it and wherever
possible we'd like to use that Id associate with each record as our key property cell say post.
Id like so then I'll close off that div.
Then inside of here I'm going to put in a icon.
If we take a look at our mockup really quick just as a reminder I don't saw the mock up up.
I don't know that the mock up up.
I'm not going to waste any time but essentially on the left hand side of every post we want to show
that icon.
Kind of like of a user or something like that so I'm going to put an italics here with a class name
of large middle Alliant icon user like so
after the tag I'll put down a div with the class name of description.
This is not description but content that's better.
And then inside of that div I want to get a class name description.
Inside of the description div or put down an H to that has the post-up title says the title of the post
and then underneath it will put a paragraph tag with the actual post content which is post-cart body.
Now I'm not making up these two properties right here.
You'll recall that we looked at that post and point just a little bit ago.
Over on the Jason placeholder website.
So if we go down just a little bit here is that posts and point I can open it up and I see that every
post has that title and body.
So that's why we specifically put post-START title and post body OK.
That looks pretty good.
I think that we've got everything we need for right now.
I need to do is make sure that I call render list for my render method.
So I'm going to go down to the render method.
I will remove the console lock.
I'm going to give this div a class name of UI relaxed divided list and then inside the div itself I
will remove the hard coded text a post list and I will replace it with this dot render list.
OK I think that's just about it.
I'm going to save this file and then I'm going to flip back over to my application and we can see the
list of posts appear on the screen.
Awesome.
All right so this definitely looks good.
We're definitely loading up some data and showing it on the screen appropriately.
Last thing we do is make sure that we show the title of the user or the author's name right underneath
the post.
So let's I'm going to try again.
I'm pretty sure I got that diagram up here.
I apologize for not having it.
Here we go.
That's better.
OK so we've got the post list put together.
Remember we had said that we wanted to make a separate component called user header and show it at the
bottom of each post.
So we still have to tackle that.
Let's take a quick pause and we'll start to figure out how we're going to address this problem in the
next video.
- Memoizing Functions 263.1. Memoization Issues{yarn add lodash --save}(Section 19: Redux Store Design)
In the last video we saw the real issue that's going on inside of our project we are overfishing our
users.
We only have to fetch each user once but right now we're fetching them 10 times in very short order.
So we need to figure out some way to fix this in this video.
We're going to start taking a look at one possible solution.
This is going to be just a couple of lines of code that we're going to change but it's also kind of
hard to understand exactly what's going on with this solution.
So that's why we're going to take a look at two possible ways of fixing this problem.
OK.
So first things first.
I can give you a little bit of background on a helper function that we're going to use inside of a new
browser tab.
I'm going to navigate to load ashed dot com slash docs.
We've looked at load ash very briefly before load ASH is a utility javascript library.
It has a ton of functions built into it that make writing up javascript just a little bit easier on
the search bar on the left hand side.
I'm going to look up a function called Memel eyes.
So this is a function that we're going to use to fix our problem.
The memorized function is kind of hard to describe with words.
I'm not even going to bother to try to do so.
Instead we're going to write out a really quick code snippet example to help you understand what this
memorized thing does and how it's going to help us solve this problem.
All right so onload and stuck come I'm going to open up my chrome console.
Now make sure that you are on load ashcan as well if you want to write the same code.
The reason that I want you to open up your console on load ash is because the load Eshe library is automatically
injected onto Windows scope.
So we can write out a simple underscore like so and that is a reference to the load ash library.
And again that is only a pixel on lodestar column.
If you go to some other Web site you're not going to have it available on Windows scope.
All right.
So inside of here we're going to write out a quick function that is very similar to our fetch users
function inside of our project.
So I don't want to create a new function called Get user.
This is going to be called with an ID.
Now I'm going to go down to a new line here to get a new line inside of your chrome console.
You can hit shift enter like so if you just hit enter it's going to try to run that code which is not
what we want just yet.
Then inside of here I'm going to try to make a network request.
With that give an ID.
Remember the fetch function is built into your browser.
It will make a network request.
Now we do not have any API or anything like that hooked up on lodestar.
So if we just call Fettes right now with some random ID we're probably going to see a 404 not found
error message which is totally fine.
I just want to show you that we can make a request from inside this function and you're going to very
quickly see how memorize changes the behavior.
We're going to see that 404 but it's totally fine.
You're still going to be able to see exactly what is really happening with.
OK.
And after that I'm going to return made a request like so as a string and then I'm going to close off
that function.
All right so now we have the get user function and we can call it by saying get user and then passing
in some random number here like I'll put into.
So it says made a request and you can see my network request log that I made a request to slash to.
Now in this case it just happens by chance that Slash to is a valid route on this Web site.
So we did not actually get a for a for in this case but suffice it to say you can see that we made a
request here right.
We called it user and we made a request that's all I want you to understand right now.
Likewise we can call it user with three and we made a request as well.
And we saw the string done here made a request.
OK.
Now it's time to focus on mammals.
So I'm going to create a new variable called minimalized get user and that's going to be the result
of calling underscore men Alais and then I'm going to pass in my get user function like so.
Notice how there are no parentheses on here after get user we just call them lies and we pass in the
user function itself.
Now when we do that memorize is going to take our function it's going to wrap it up with a bunch of
additional code and it's going to return a new copy of our get user function and this new copy is what
we refer to as the memorized version of the function.
So this right here memorize get user is a new function that has the same behavior of as our old function
that we were just wrote a second ago.
The only difference is that we can only call memorize user 1 time with any unique set of arguments after
we call it one time we can still call it.
But the original function is not going to be actually invoked.
Instead memorize is just going to return whatever we had returned previously the last time we ran it
with the identical set of arguments.
Now even when I say that again with words it doesn't make a lot of sense.
So let's try looking at a quick example here.
I'm now going to call memorized.
Get user and I'm going to pass in theory as the argument now the first time that I call this with three
the request is going to made it is going to run our original function and we can notice that is the
case because we see the request three up here was made and we see that we returned the value made a
request.
Now here's the key part.
Clear the requests log and I'm going to run that same exact call a second time the second time I do
it.
The request is not made.
So when we memorize a function the original function only runs one time just once.
And then any sound we call it again in the future the function itself is not going to run.
Instead we are just going to return whatever was returned the previous time.
So we still see the return value of made a request right here.
But we did not run the original function and actually make the request but that's only on a basis of
the unique arguments that we pass in.
So if I pass in a new unique argument year like say two instead of three.
Now the first time I run this function with to the original function get user is going to be ran again.
So I can run this to all see it makes the request now clear that read log or run to again.
And now you'll notice that it did not make the request.
Likewise I can try to do this with for the first time it's got to make the request.
But then each subsequent time it does not make the request.
And so I can run this now as many times as I want with four I can run it as many times that I want with
three to and it does not make the request.
Again just my guess.
This is basically the perfect solution for our problem.
We only want to build a call our action Creator with a unique ID one time because we only want to fetch
each user one time and then if we call our action creator with that same ID again in the future we don't
really want to make the request at all.
So memorizing our action creator could be a very good solution here.
So let's take a quick pause.
It'll start to implement this inside of a project in the next video.
263.1. Memoization Issues{yarn add lodash --save}
In the last video we got a quick overview of doing function memoization inside of Javascript.
So we're not going to install the load Eshe library into our project and use it to memorize one of our
actual creators so that it does not constantly fetch the same user over and over again.
So I can flip on over to my terminal.
I'm going to start my server with Control C and then I'll run NPM install dash and save load ash.
This is going to take just a moment to install so I'll just let it do its thing and then once it's all
done I'm going to start my server backup with NPM start as usual.
All right so NPM start and there we go.
Everything launches Bekka.
259.2. Finding Relevant Users(Section 19: Redux Store Design)
All right so now inside the render method we're going to look through that array and find the user that
we want to display.
So to do so I'm going to say Konst user and then we're going to use this Propst users.
That's the array of users dot find like so not just you know find is a built in method on Javascript
arrays we can call it with a function.
This function is going to be invoked with every element inside of that array.
And so I will we will refer to that argument as simply user and then as soon as we return true from
this inner function right here the entire find function is going to stop and return whatever element
we had return true for now.
When I actually say those words out head sounds a little bit confusing.
So let me just give you a very quick example.
I'll pull open my console again.
We'll just do a real quick test here so I can say Konst colors and I'll do my array of colors again
and I'll add in like say a blue and red like so I think I've got a typo there.
Let me fix that.
OK so now to get say blue out of there we can do colors find and then for each color I want to return
the results of color being compared with the string blue.
So now which ever first element inside of our array returns true for this comparison right here.
We're going to return that color from the overall expression.
And so we're going to do the same thing to find that user that we care about.
So I'm going to say find for every user find a user with an ID equal to this Propst user ID and I'm
going to try to put that on one line.
Actually I'll just zoom out so you can see the entire line like so.
So this will find just the user that we care about.
Now keep in mind when the application first is rendered onto the screen we will not have a list of users
here.
We will have an empty array but the user that we care about is not going to actually be available.
So right underneath this will say if there is no user found.
So if we did not find some appropriate user then we will just return nothing for right now.
So just don't return anything.
I don't want this component to show any content on the screen.
I don't even really think it's appropriate to put loading although we certainly could we can return
it.
That said loading.
Like so.
But also keep it simple and all return NULL to indicate that I don't want this component to show anything.
Now if we did find a user We will instead put the user's name inside of here.
So the user's name is accessible on the name property so say user name like so.
All right.
And then very quickly I want to throw in one or two quick class names here.
So on that div I'll put in a class name of simply Hetter like so.
All right so I think this should be just about good enough.
So let's take a save on this file and we'll flip back or the browser and we'll test this out really
quick.
All right.
Now I got a nasty error message here so it cannot read properly.
Find of undefined.
Let's make sure I got that in all places up.
So looks like I probably have a little typo somewhere.
Let's see I've got users.
I'm not going to make you.
Oh that's right.
Little mistake right.
We defined map state to prop so we did not pass it off as the first argument to connect second to make
sure that I do so really quickly.
There we go.
And now if I flip back over and refresh.
Right.
That's better.
Now it's still loading just give it a second here.
There we go that's perfect.
OK.
So I can now see that on every blog post I've listed out the authors name.
So I see Leon Graham for the first 10 and then I see the second name of Irvin Howell and then Clementine
Bach and so on all the way down to the bottom.
So it definitely looks like this has worked out pretty well.
But there's one little issue you remember I mentioned there is one little issue now before I tell you
what that issue is.
There's a little refactor that I want to show you for the user Hetter component.
So take a quick pause.
We're going to do that quick refactor and then I'll show you the kind of a real big issue that our application
currently has.
So quick pause and I'll see you in just a minute.
258.2. Displaying the User Header(Section 19: Redux Store Design)
We want to make sure that we call an action creator inside of here that's going to fetch the appropriate
user.
So at the top we're going to make sure that we import the connect function and the action creator itself
and we will use the connect tag to wire up the action creator to the component.
So at the top I'm going to import connect from re-act redux and I'll import fetch user from actions.
So now down at the bottom I'll place the connect function and make sure I wrap my component with a second
set parentheses.
Right now we did not have a map state to prop's function.
I'm going to pass a null as the first argument and then for the second argument I'll do an object with
fecche user OK.
It's now the last thing we do inside of our component.
When ever this component appears on the screen we're probably going to want to make sure that we attempt
to patch the given user that this thing is supposed to show.
So I'm going to define that component did mount inside of here when whenever user header is displayed.
I'm going to call my action Creator through this stuff.
Propst fetch user.
And then remember we need to pass than the ID of the user that we want to fetch.
And as we saw just a second ago we are passing in the idea the user that we want to fetch as a prop
called user id so back over here I'll make sure I call fetch user with this stuff Propst user id OK.
And that's pretty much it.
So we can save this and flip back over to my application and it looks like everything still works.
Now we don't have any redo sir to actually pick up the data from the request that we are making and
eventually get access to it and show it on the screen.
So we'll take a quick pause right here and start to tackle that in the next video.
Now before we move on I want to remind you I told you that we were going to run into one or two little
challenges.
So if you are looking at some aspect of this application right now and saying Hey Stephen you know what
I don't think this is working the way we expect it to work.
That is fine.
I'm not going to tell you exactly what it is because I kind of want you to stumble into it yourself.
But again if you see something that looks weird that is totally fine and we're going to fix it up in
a couple of videos.
OK.
So let's take a pause right here and we'll start working on a redo in the next video.
263.3. Memoization Issues(Section 19: Redux Store Design)(Section 19: Redux Store Design)
So let's try the second option here.
Let's try to remove the memoires out to the outer function and I want to make sure I clean up the parentheses
down there as well and then I'll try minimalizing the inner function right here.
So right in front of async I'll put underscore minimalize and I'll make sure I put my closing print
see right there in line 21 for me.
OK so now we are memorizing the interior or inner function.
This is the one that actually gets invoked with redux thunk.
So hopefully now redux sunk will only be able to call that function one time and never again after that.
All right so I'm going to save this and we'll flip back over and we'll very quickly see if we're still
making all these requests.
So even with this approach we're still running into issues and it's not doing what we expect.
So why is that.
Well remember every single time that we call this action creator we are going to declare a new function.
We recreate this function right here in memory every single time that we call fetch user.
So we recreate this function and then we memorize it and return it.
Now we definitely memorize the internal the interior function right.
So in theory it's not going to be called multiple times by redux stunk but really remember what happens
here every time we call fetch user We're going to create a new version of the interior function and
memorize it every single time.
So even though we are memorizing this thing we are memorizing a new version of the function.
Every time we call the action creator.
So every time we call the action creator new memorized version comes out and we can successfully call
that memorized version and the original interior function right here will be invoked because we are
recreating it every single time.
So like I said this problem is not quite as crystal clear as you might expect.
So now that we understand why we cannot just throw memories inside of here willy nilly.
Let's take a quick pause.
We'll take a look at how we're going to solve this problem in the next video.
- Argument Values(Section 19: Redux Store Design)
In this video we're going to move on to our second big rule around reducers.
So with this rule we say that producers are supposed to produce or return state or data that is going
to be used inside of our application and the producer has to do so using only the previous state from
the last time that it was called and the action object that has been dispatched and is being passed
into a given reducer.
Now understanding this text right here is a little bit challenging.
So we're going to look at a diagram or to help you really understand what's going on here.
All right.
This is a diagram of what happens to your reducer.
The very first time that it gets called inside of your application.
Now as I mentioned in the last video when you first start up the redux application each reducer is going
to be automatically called exactly one time.
So it is a automatic invocation that essentially allows your reducers to specify some default state
value the first time your seducer gets called during that initialization process.
It's going to receive two arguments.
The first argument is going to have a value of undefined.
And then the second argument will be some action object that we might refer to as action number one
because it is the first action that the reducers going to see.
So it is then up to the reducer to take these two arguments right here and return some initial state
value.
Now we really already went through this process right here.
Back when we put together the song's application in the last section I'm going to pull on some code
from that application onto the screen really quickly OK.
So here's our selected song reducer.
So when our application first started up selected song reducer was invoked automatically.
One time let's imagine that the code for invoking at one time was placed right here.
So redux internally did something like selected song reducer and it passed in a first argument with
the value of undefined.
And then the second object is going to be some initialization action object.
We don't really know what type that this action is going to have.
We just know that it's going to be in there it's going to be an action object with some mystery type
property that we don't really know.
So the first time that our reduced or gets called we're going to essentially look at that first argument
right there and very quickly realize that it is undefined.
That's why we put a default value for selected song right here.
Remember what this syntax right here really does.
It's a little bit of yes 20:15 syntax that is essentially the equivalent of saying if selected song
is equal to undefined then change the value of selected song to be no instead.
So again the very first time we call the reduce our first argument is undefined.
We don't really want to deal with that value of undefined.
So we are going to default it's value to instead be null and that little option right there that defaulting
is only going to take place the very first time that a reduced or gets in vote member all the equals
nil right there does is check to see if selected song is equal to undefined.
If it does it's going to update the value of that argument to be NULL instead.
We're not going to always default a argument like this to be equal to nil.
In many cases we will instead defaulted to be an empty array or it might be an empty string or some
number like the number 10 or something like that.
It really just comes down to the purpose of the reducer that we are working on to decide on the default
value.
But in the case of selected song reducer a default value of Noal made a lot of sense because that meant
no there is no currently selected value inside of our application.
OK.
So I can clean that up really quick and we're going to flip back over to this diagram I guess that's
what happens the first time the reducer is cult now where things start to get really interesting is
the second or third or fourth or fifth time that the reducer gets caught the next time.
Like the second time that this producer gets called The first argument is no longer going to be equal
to the value undefined.
Instead it's going to be whatever the reduce or returns the last time that it was ran.
You'll notice that the first one to reduce ran it returned what we call state view one right here.
So the next time the second time that the reducer gets called The first argument will then be equal
to state v 1.
So essentially that first argument into your reducer is always going to be what ever it was it returned
the last time it was ran.
So you can kind of imagine that we've got this kind of acyclic action where our reducer just keeps on
getting called with its own value that is turning over and over again.
And the only real change inside there is the action object.
The only thing that changes each under a or gets called is that action object and the type in Paillard
property inside of it I get so that's what the second rule right here is talking about.
Our producer must return some data or some state using only the previous state value that it returned
and the action object.
So now that we have a better idea of rule number two right here let's take a quick pause.
Ill move on to rule number three.
Created Text For URL [www.heraldlive.co.za/news/2020-07-07-man-gets-life-for-double-murder-of-his-girlfriend-and-her-cousin/]
Fucking piss ass shit cunt
This reverts commit fe791de43e9bd33711e5bc9b6ed360cccd22acb1.
27.3. Product Details & Smart vs Dumb Components{ Computed price Property; Computed Properties with Arguments?; Smart and Dumb Components }
Computed price Property
Let's do this! Add a computed option with one computed property called price(). Inside, return this.product.price - to reference the price of the product prop and divide this by 100. Good start! To convert this into a string that always has two decimal points, we can use a fun JavaScript function that exists on any Number: .toLocaleString(). Pass this the locale - en-US or anything else - and then an options array with minimumFractionDigits: 2. Pretty cool, right? I'll even add some docs to our function. I'm over-achieving! Now that we have a computed property called price, we can use it with {{ price }}, as if price were a prop or data. We know that computed properties - similar to props and data - are added as properties to the Vue instance, which is why we can say things like this.price. But behind the scenes, when we access this property, it will call our method. As a bonus, it even caches that property in case we refer to it multiple times.
Computed Properties with Arguments? Oh, and by the way: this is one of the reasons why I created a specific component for rendering each product. If we did not have this component... and we were rendering this data inside the ProductList component, we wouldn't be able to use a computed property... because we would need to pass an argument: the product whose price we need to calculate. Instead, we would have needed to create a method... which isn't the end of the world, but is less efficient. Any time that you're creating a method to return data, it's a signal that you should considering refactoring into a smaller component that could use a computed property. Anyways, now when we move over... we don't even need to refresh: there is our beautiful 30.00 price. What a bargain!
Smart and Dumb Components Before we keep going, I want to circle back on a controversial decision I made earlier: the fact that we kept the products data inside catalog.vue even though the product-list component is technically the deepest component that needs it. If you look at catalog.vue, it holds the AJAX call and pretty soon it will hold logic for a search bar. But... it doesn't render a lot of markup. I mean, yeah, it has an
up here and a down here, but its main job is to contain data and logic.
Compare this to the product-list component: index.vue. This doesn't have any logic! It receives props and renders.
Well... surprise! This separation was not an accident: it's a design pattern that's often followed in Vue and React. It's called smart versus dumb components, or container versus presentational components.
This pattern says that you should try to organize some components to be smart - components that make AJAX calls and change state - and other components to be dumb - that receive props, render HTML and maybe emit an event when the user does something.
product-card is another example of a dumb, or presentational component. Sure, it has a computed property to do some basic data manipulation, but this is just a component that receives a prop and renders, maybe with some minor data formatting.
To compare this to the Symfony world, one way to think about this is that a smart component is like a controller: it does all the work of getting the data ready. That might involve calling other services, but that's not important. Once it has all the data, it passes it into a template, which is like a dumb component. The template simply receives the data and renders it.
Like all design patterns, keep this in the back of your mind as a guide, but don't obsess over it. We're doing a good job of making this separation in some places, but we're not perfect either, and I think that's great. However, if you can generally follow this, you'll be happier with your components.
Next, now that we're loading data via AJAX, we need a way to tell the user that things are loading... not that our server is on fire and they're waiting for nothing. Let's create a Loading component that we can re-use anywhere.
yogstation13/Yogstation@97f8b5755d...
Tuesday 2020-07-07 21:11:37 by wejengin2
[boring] Fixes Active turfs part 3 (#9143)
-
who did this
-
another one
-
holy shit im stupid
-
another one
MarcSabatella/MuseScore@cd92ec6f01...
Tuesday 2020-07-07 21:41:13 by Marc Sabatella
fix #276141: no space for lyrics in continuous view + collect_artifacts
Resolves: https://musescore.org/en/node/276141
A common complaint since the release of MuseScore 3 is
that we no longer allocate additional space between staves
for lyrics and other elements above/below the staff,
when in continuous view.
That's because these calculations in page view can be optimized
so they only need to be done for affected systems on each layout.
In continuous view, there is only one system,
so it would mean a full layout, which is very slow.
But MuseScore 2 did this, and people writing vocal music especially
were accustomed to this automatic staff spacing.
Since lyrics were about the only thing that did this spacing,
it wasn't as expensive as it would be using MuseScore 3 autoplace.
And yet, MuseScore 2 was extremely slow with large scores,
because it lacked any range optimizations, even in page view.
This change finds a compromise that should work well.
On the initial layout in continuous view, we do build a full skyline,
so it is easy enough to add space for each staff then,
and any performance penalty is paid only at that time.
Any extra space needed for this is remembered for subsequent layouts.
On future layouts, we do use a range, so we only have a partial skyline.
The code here calculates the space needed just within the current range,
but it also compares this with the remembered value,
so uses whichever is larger (and remembers this new value if different).
The result is that the spacing is correct when first opening the score,
or when first switching to continuous view.
After that, any edits that increase the required space
(such as adding a new verse of lyrics)
will do so as expected.
If you later make a change that reduces the amount of space requires,
we cannot reclaim that space, since a full layout would be required
in order to detect that we truly don't need the space anywhere.
But you can always reclaim it by switching to page view and back.
The code to do the partial skyline comparison is not free,
but it happens only once per staff per layout,
so in theory it should have a negigible effect on performance.
If this assumption turns out to be wrong,
we can switch to the code that skips the partial skyline comparison
except on the initial layout.
This is included but ifdef'ed out.
newstools/2020-sowetan-live@4154f1471b...
Tuesday 2020-07-07 23:42:40 by NewsTools
Created Text For URL [www.sowetanlive.co.za/news/south-africa/2020-07-07-man-gets-life-for-double-murder-of-his-girlfriend-and-her-cousin/]
< 2020-07-07 >
yogstation13/Yogstation@97f8b5755d...
Tuesday 2020-07-07 21:11:37 by wejengin2
[boring] Fixes Active turfs part 3 (#9143)
-
who did this
-
another one
-
holy shit im stupid
-
another one
MarcSabatella/MuseScore@cd92ec6f01...
Tuesday 2020-07-07 21:41:13 by Marc Sabatella
fix #276141: no space for lyrics in continuous view + collect_artifacts
Resolves: https://musescore.org/en/node/276141
A common complaint since the release of MuseScore 3 is that we no longer allocate additional space between staves for lyrics and other elements above/below the staff, when in continuous view. That's because these calculations in page view can be optimized so they only need to be done for affected systems on each layout. In continuous view, there is only one system, so it would mean a full layout, which is very slow. But MuseScore 2 did this, and people writing vocal music especially were accustomed to this automatic staff spacing. Since lyrics were about the only thing that did this spacing, it wasn't as expensive as it would be using MuseScore 3 autoplace. And yet, MuseScore 2 was extremely slow with large scores, because it lacked any range optimizations, even in page view.
This change finds a compromise that should work well. On the initial layout in continuous view, we do build a full skyline, so it is easy enough to add space for each staff then, and any performance penalty is paid only at that time. Any extra space needed for this is remembered for subsequent layouts. On future layouts, we do use a range, so we only have a partial skyline. The code here calculates the space needed just within the current range, but it also compares this with the remembered value, so uses whichever is larger (and remembers this new value if different).
The result is that the spacing is correct when first opening the score, or when first switching to continuous view. After that, any edits that increase the required space (such as adding a new verse of lyrics) will do so as expected. If you later make a change that reduces the amount of space requires, we cannot reclaim that space, since a full layout would be required in order to detect that we truly don't need the space anywhere. But you can always reclaim it by switching to page view and back.
The code to do the partial skyline comparison is not free, but it happens only once per staff per layout, so in theory it should have a negigible effect on performance. If this assumption turns out to be wrong, we can switch to the code that skips the partial skyline comparison except on the initial layout. This is included but ifdef'ed out.
newstools/2020-sowetan-live@4154f1471b...
Tuesday 2020-07-07 23:42:40 by NewsTools
Created Text For URL [www.sowetanlive.co.za/news/south-africa/2020-07-07-man-gets-life-for-double-murder-of-his-girlfriend-and-her-cousin/]