- Read Tutorial
- Watch Guide Video
And we had already had it kind of set up to only display the courses we are enrolled in by using these css tags here. But the problem was that we still had all of those courses in our state here.
so it was calling this function as many courses as we had which was displaying a lot of empty courses. So by doing that we removed all of the empty slots that we had and now we're left with only the courses that we are enrolled in. What we're going to solve in this guide is the ordering. You'll notice when I add in the first one here it displays at the top, when I add in something in between this one and this one such as typescript development displays in between here.
So we're going to solve the ordering in this guide and this one's a little bit more complicated. But what we first have to do is, think about a problem, so we need to somehow keep track of the courses we've already added in here. And the way we can do that is by keeping record of these courses in our component state and we can do that by creating an array in our state called enrolled so we can store the ones we've already enrolled in, in this piece of state.
So let's start off in schedule.js
by typing out this.state equal to a javascript object with enrolled and an empty array or collection
this.state = { enrolled: [] }
and hit save and that should be good there. Now let's just get rid of this comment here of filter out our course instances that we are not enrolled in let's get rid of that so we're left with ordering and empty slots.
Now we don't want to map over our props.courses at this point. We want to map over our state here that has enrolled and the reason we want to do that is because we're going to store in the ones we've already enrolled in. That way they will be first such as if I had algorithm bootcamp and then introduction to JavaScript and then up and running with redis you'll notice that it appears here at the top like I said.
Basically the idea here is that if we have we already have these stored in our component state here then when we render it, these will appear first instead of this redis one and the reason this is appearing first is because it's coming in our array first like you'll see in our index.js in our actions that it's the very first one.
So that's why it's appearing first is because it's going through our props.courses here which is going to display this redis one very first because it comes first. So again the idea is to somehow get these to display first by putting them into this array. So they come first when we rerender our application so that might take a little bit to wrap your head around.
Feel free to pause the video and think about that a little bit and try and understand the logic behind this before we move on, or it might get a little more confusing. All right so in our code here let's type out the componentWillReceiveProps method and this accepts a parameter called nextProps and the reason we're going to be using this method is because this is a part of the react component lifecycle and if we go to one of these articles I'll leave both of these in the guide notes below.
So in this one on, if we search componentWillReceiveProps we'll see a little bit of how this works so it says our component was doing just fine, when all of a sudden a stream of new props arrive to mess things up. So in our case our stream of new props it's going to mess everything up, is this Redis course right here we add it and it messes things up. So back in our article it says perhaps some data that was loaded in by a parents component did mount finally arrived and is being passed down before a component does anything with the new props component will receive props is called with the next props as the argument.
Okay so this is the key thing we need to look at it says we are now in a place where we have access to both the next props and our current props and the reason that's important is because then we can say okay we have all of our new props which are the two courses here. The UX for Developers and Up and Running with Redis and then we have access to our previous props which is just UX for Developers.
So that way we can say okay well we already know that this is in here. Let's go ahead and push this in our array that we want to render our enrolled array here and then we'll push in the one that's coming in next, that way there will be an order. So the idea is, okay let's check our previous props, let's check our current props and see if there's anything in there and if there is let's put it at the front of the array so it renderers first and then we'll say okay let's check the next props and if there's anything there that is enrolled then we'll throw it in our enrolled array and it will be after that since we've already run through our current props.
So the first thing we want to do is not render anything from our this.props.courses because that's going to be checking our props in this order again. So we need to check our enrolled, so let's copy enrolled let's say this.state.enrolled. And this is not going to do anything at first we won't be displaying any data. The reason being is because this.state.enrolled contains nothing and we're not adding to it, but our courses are still containing or courses. So if we add something nothing will display.
Okay, so to fix this we just have to add stuff in here. So if we go to our componentWillReceiveProps and let's say console.log and I'm going to type out a separator kind of line here so we can see okay these are our new props and make sure to add in parentheses or ticks.
Then I'm going to copy that and actually I'm going to put end here I'm going to name this one start and then I'm just going to put a separator here to separate the two.
componentWillReceiveProps(nextProps) { console.log(`-----start-----`); console.log(`----------`); console.log(`-----end-----`); }
So I'm just going to put in the separator and we just know that our current props are going to be in between start and the separator and our next props are going to be in between the separator and end. So let's go ahead and let's map through each of these and then display the title of each. So for this one let's say this.state this is going to be our current prop. So this.state.enrolled.map and then let's say this.props.courses.map that so console.log(course.title); let's just copy this and let's say instead of this.props let's say nextProps.
componentWillReceiveProps(nextProps) { console.log(`-----start-----`); this.props.courses.map((course) => { console.log(course.title); }) console.log(`----------`); nextProps.courses.map((course) => { console.log(course.title); }) console.log(`-----end-----`); }
This might crash let's see OK so let's check our console and we're getting nothing because we have no props currently there is no courses in here.
So if we had one we notice that our next props is displaying algorithm bootcamp and our first props and let's just put in some line breaks here and then redo that. So we have space between these and you'll notice our next props has Algorithm Bootcamp and our previous prop still has nothing.
Now it's add in UX for developers and you'll notice it says okay our previous props has Algorithm Bootcamp which is what we previously had and then our next prop says UX for Developers and Algorithm Bootcamp.
So what we need to do here is whenever we get new props we need to push it to our enrolled array. So let's go ahead and let's create that array up here and call it var newEnrolled. Then in our next props let's just say okay if the course is enrolled lets print the title and then let us push it to our array and technically this is redundant, we don't need this if statement, we might remove it later but I'm just going to leave it for now.
The reason that it's redundant is because we already know that it's enrolled because we're only allowing a course into our props if we're enrolled already. So basically we already know it's enrolled and we don't really need to be checking that. But let's leave it there for now anyway just to ensure things are working. So newEnrolled.push and lets type in course, so now we know that these courses are being pushed through and we're mapping over them right here, let's check in our app and see if this is working. So Algorithm Bootcamp and it's not displaying.
The reason why is because we haven't set newEnrolled to be a part of enrolled yet. So the way we can do this is first let's check this guide and he says here in the guide that we can call setState on it. And the most common use case of this method is to act on particular prop changes to trigger state transitions, so that's exactly what we're doing. So let's just say this.setState and then let's say enrolled and then set it a value of newEnrolled.
this.setState({ enrolled: newEnrolled })
OK back in our app it should be working now. Let's add in Algorithm Bootcamp and you'll notice it's right there which is great. And then lets add in UML for Developers and it's there as well.
But our problem is still here so let's add in Up and Running with Redis and you'll notice it's still at the top. So we have our previous props which is Algorithm Bootcamp and UML for Developers and then our next props which is Up and Running with Redis and Algorithm Bootcamp and UML for Developers. So what we have to do is when we're mapping through this one we need to push these to the array first and then Up and Running, so let's go ahead and try that. Let's say if course.enrolled newEnrolled.push course.
console.log(`----------`); nextProps.courses.map((course) => { if(course.enrolled) { console.log(course.title); newEnrolled.push(course) } })
Then let's move this console log into here and see that and let's wait for this to reload. Now let's add in a couple and you'll notice we have this error we don't really need to worry about this right now.
This is just the key problem so don't worry about that. But the reason that's happening is because we have duplicates so in our render we're saying the key is this.props.course.indexOf(course). And that doesn't work because we have the same exact course here Algorithm Bootcamp twice and that's a problem, so ignore that for now.
The main thing we need to notice is that we're adding Algorithm Bootcamp twice and the way we can solve this is we know it's been added in here already. So we need to check in here and say okay if this course is already contained in our array we don't want to push it to our array. So let's add a condition here and say and not newEnrolled.includes(course).
if(course.enrolled && !newEnrolled.includes(course))
It's not going to say OK if the course is enrolled and we don't have it in our array let's add it, so we shouldn't be adding it twice. So we'll add Algorithim Bootcamp then Problem Solving then lets add this one, and you'll notice it works.
But we have another problem. So you might notice that when we add another one it comes after and that's working. But as soon as we add another one it reverts the order back again, so it's all mixed up. So the way we can solve this is by actually instead of going over the current props we can just say OK this.state.enrolled and that way we will get the correct order and then it will go over properly and add them in the way we want. So let's save that and say add and that comes in first, so we have problem solving as our previous props and then we have up and running as our next. So it's going to add in problem solving and then it's going to adding up and running with Redis.
All right so I think that should solve the problem let's just kind of play around with it for a second and see if that's the way it is. Try removing it with the buttons over here and it looks like it's working, it looks great. Let's just make sure nothing is broken here. Yes so it's adding in the way we want and they're in order. Let's go ahead and get rid of these console logs and clean up this function a little bit and yeah that should be good, so this is working now.
The next thing we need to handle is empty slots we need to make sure that it's displaying five empty slots instead of nothing and then we should be good. So we will handle that in the next guide, let's go ahead and commit our code. So git status
, git add .
, git commit -m "fixed ordering of schedule"
, git push orgin master
.
And I will see you in the next guide.
Resources
https://medium.com/@baphemot/understanding-reactjs-component-life-cycle-823a640b3e8d
https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1