Full Stack Flask, React, and Postgres, pt 2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right welcome back in this video we're going to build out our front end using react so uh if you didn't check out the last video we set out our back end using flask that is currently running and we can see the activity here in this um terminal here so i'm going to open up a new terminal window i'm going to make sure that i'm in the top level so in baby tracker make sure that you're not in back end so you cd back out from here run npx create react app and then i'm going to just call it front end and the reason i'm doing that is because uh we're in this baby tracker already and this is just the way that it's organized so we'll just call it front end and there you can see the folder already populated so we'll uh let this uh run for a second and then jump back in when it's done installing okay now that that's finished up uh we're going to change directories into our front end and we're going to install two libraries the first is axios which is an http request library it's just a matter of preference we could simply use the fetch api uh but with axios i just prefer how it looks how it reads uh and we'll be using a couple of different operations and i feel like axios does a good job of uh setting us up pretty easily uh the second library will be uh called date fns and it's just a uh a daytime library uh with a series of helpers that'll be helpful for us when we're formatting our timestamps so i'm going to change directories into front end and then i'm going to npm install axios and date fns okay so that's finished up we're in our front end i'm going to open up this directory and open up our app.js file uh we can also go ahead and just npm start for now and uh that's just going to be your basic react logo spinner and we'll do some updates so we've got that going here i'm going to flip back over to the project and we'll get started so we're not going to need the logo uh we're gonna we're gonna grab axios for now and uh we're also going to grab um format from date fns so i like to have my library dependencies at the top and then any like styles and components next that's just kind of how i structure it the next thing is we're gonna set a base url so for now we're just using localhost 5000 that's where our flask server is running um and we'll use that as a base and then we'll append on uh our different endpoints for our various operations so we'll just set this up here at the top and similar to so it's hdb similar to our flask app where it's it's pretty basic for now we're just going to keep this all in our app.js obviously if this application were to scale you'd probably want to do a little bit more organization and structure with different directories in your source directory here but we're not gonna worry about that for now so we have our base url we can actually get rid of um everything inside so we can keep this uh app header that's fine um okay so let's go ahead and start with a couple of things so we're going to be using uh hooks in this and so we're going to import the use effect and use state hooks from react and then we'll get our basic uh set of pieces of state set up at the top so the way that this is going to work is we're going gonna have just a simple uh like a simple little form with um an a text input and a submit button and that's going to allow us to uh create our events with descriptions uh we'll also have a way to edit our events and delete them um and then we'll just list them all out as well so we're gonna have a piece of state for our description this is going to keep track of the this is gonna uh serve as our like controller for the controlled component uh which in this case is uh gonna be our text input so we'll set it with an empty state or sorry an empty string as its state so that should be good for now and then let's go ahead and set up our actual ui down at the bottom so we're going to have a form and inside of it we'll have a label which is going to be description the label has this html4 prop which lets it know like which input it's it's uh attached to so it's going to be the html4 description and then we'll have an input where the type is text the name is description the id is description uh the value making this controlled is going to be this description piece of state here and then we're going have um an on change handler so you could do this in line if you want um i'm gonna create a handler for it so we'll do on change equals handle change and this is going to pass in our uh event so we'll do cons handle change it takes in an event and then we will set our description to be e dot target dot value and so now what will happen is anytime this input changes because the value is tied to description uh we'll now be able to set our description to that value that's being typed inside of our um uh description and input field um cool we're gonna eventually set up uh an input um or excuse me a uh submit handler that's more sophisticated for now we can see this in action we'll say const handle submit equals e so event again we're going to e dot prevent default so when you submit the default behaviors to refresh the page we don't want to do that we just want to append our next event so we're going to prevent default and then for now we'll console log the description so let's flip back over okay so we have our description we have our input we need a way to submit that with a button but let's clean up the style just a little bit so what we're going to do is over in uh app.css we're just going to make our input and then we'll do this for a button too we'll do display block and then margin we just give it uh eight pixels on the top and bottom and then zero left and right and then let's add that button so the form we're going to connect it by saying on submit is equal to our handle submit method here and then we're going to have a button beneath our input and we'll say submit and uh that will give it a type of submit as well just to be clear as to what this button is intended to do so now we've got our description so if we open up the console i'm just going to clear this out and we do like new bottle and hit submit now we can see there's our description so obviously we want to do some more sophisticated stuff with this but you can see that it's working and if we open up the components tab here inside of our app you can see the state is being updated as new bottle and you can even parse the hook names with that little magic wand and you can see description so that's uh the input is connected to our state as intended so that's great um let's keep on chipping away at our application so back in the code let's go ahead and uh we should have a list of events already at our events endpoint so the first thing let's list out uh the events that we currently have so using our use effect hook and we'll uh we'll create a new method called fetch events so we'll see fetch events this will be an asynchronous function and we'll say data is equal to a weight axios dot get and we're going to use a template literal so that we can use that base url that we set up before so base url and then slash events is the endpoint that we're uh trying to hit uh from there we can console log the data just to see what we're getting and then to uh to actually call this inside of our use effect we can fetch our events and we just want to do it on mount for now so we will leave our dependency array empty so we should fetch our events if we save this flip back over open the console quick note here something that i missed in the back end video so you may have run into an error if you just tried to set that up and you may have seen a cores error and so uh to resolve that we need to set up uh cores on our back end so in our app.pi you want to make sure that flask cores is installed and then we want to make sure it's instantiated so in app.pi we just need to import cores at the top and then instantiate course here and then that should resolve the issue if you're still seeing cores uh errors after that you can try um shutting down both the front end and back end servers and then restarting each and those problems should be resolved and we have this object with data inside and there's our events array so we should be able to grab that if we flip back over so there's our data and we're just going to go ahead and destructure off uh events and we're going to set that equal to data.data and the reason i'm getting that is if we look there's our data object and it's got a couple of different objects within it so this is data.data and now we're just destructuring events off of that and that should be our array so we need a place to store these events so we'll create another piece of state and we'll call it events and then set events will be our updater and we'll instantiate it as an empty array and then rather than console logging our data what we'll do is we'll do set events uh and actually let's do let's do events list so that we don't have any name collisions there and then set events list and we'll do set events list to our events okay cool so we could console like that we could check the components tab but uh i trust that this is gonna work so what i'm gonna do now is go ahead and build out a little list for our events so what we can do is and actually so semantically we don't really need this header so we can just delete that and if we're being technical here we can do like a section with our form and then another section with our like list so we can make an unordered list and we're going to map over our events so for each event we're going to events.map event and then we'll return list item and this will have the event uh dot description oh events list that's why it's giving me the issue okay eventslist.map for each event we're going to create a list item and then this uh the key we should have an id so the event.id should be unique so now if we save this we can see okay so uh we've got our uh styling obviously thrown way off but um we can see our list now which is great so the next thing that we want to do is allow for the uh creation of new to-do's or excuse me new events so to do baby stuff so new events so what we can do is flip back over to our application and update our handle submit method so rather than console logging the description what we can do is we can say okay data is equal to a weight and we need to make this asynchronous now so that's async our data is going to be equal to await axios.post we'll use a template literal again and we'll do our base url slash events and then we're going to pass in some data so the data is just going to be our description and so this is the same as doing description is equal to description but with the uh this is just a shorthand way of writing it so uh from here what we can do then is we can update our to our events excuse me set up our events list so that now we have our events list being merged with data.data and we'll take a look at uh what this looks like the next uh then the next thing that we want to do is um clear out our description field so we'll do set description uh back to an empty string now um a best practice as well for this is is to create some sort of error handling this is not gonna be super sophisticated but with an async function we can do a try catch and for uh for this we'll just console.error the error.message but you might throw like a little snack bar or some sort of pop-up or something that says like hey there's an issue here um and then inside of our try block we'll do this so we can save this and flip back over and now we should be able to create a let's say 50 milliliter bottle if we hit submit now we can see that 50 milliliter bottle if you pop open the network tab you can actually see this uh happening let's see if this was it so our request was okay so we had the description with the 50 milliliter bottle and then we got our response where we've got the created at the description and the id which we all set up this response in our in our back end with flask and so because of that now we're able to grab the data and then add it to our events list which we can see here and each of these have our timestamps our description and the id nice so flipping back over um let's clean this up a little bit so our section can have like um let's do we had app header let's see what this looks like if we just flip this to section it's kind of the lazy way of doing it but okay so that kind of works and we're getting some huge spacing here let's get rid of the min height and then we can do like min height for um if you wanted to you could do min height for the app or and add the background there for this this is fine i'm not as worried about the uh the style of it okay so close that up um the next thing that we want to do is allow for the ability to um delete our events so let's go ahead and set up the method for it first um inside of app.js we can do const handle delete this is going to be asynchronous it's going to take in an id which will be the event id and then we'll set up another try catch wearable console.error error.message and inside of our try block we are just going to await axios.delete we don't necessarily need a message here you could create one on the front end if you want uh we'll do our base url slash events slash id and that's the id being passed in to this method from there what we'll do on the front end is we'll uh we're going to create an updated uh list of events and then we'll update the state so that our ui reflects the new um updated list you could uh just re-fetch the data too and that's perfectly valid so you could do like a delete and then um call fetch events again which is fine and that might work for your use for your use case for us in this application we're just going to refresh the ui without making the additional call so the updated list is going to be equal to our events list and dot filter we're gonna filter out the um event id so grabbing our events list we're filtering the event id should not equal the id being passed in so this is going to clear out that event on our ui side and then all we need to do is set our events list to our updated list so now we just need to connect that so what we can do is go down and we can modify our list item so in our events list we're going to actually create a div and we're going to grab that key and it's going to be equal to the event dot id we had that on our list item before we're just flipping it so inside of here and actually it might even be better if instead of doing a div because now we have an unordered list with a div inside of it we can try this so we can do the list item and then we can just put all of our stuff inside so our list item is going to have we're going to cut the event.description it'll have a button uh and we just put like a little x there and then on click is going to have uh our um it's gonna be able to pass in our id to the delete method so we can do handle delete with the event dot id so this is going to pass it in and then what did we need our to do or our event i keep calling them to use event dot description so now if we flip back over let's see how this looks okay that's fine uh we could do like a little inline not at all best practices for uh for styling but we're just getting something kind of quick and dirty okay so that's fine and then um let's go ahead and try and delete it so we get rid of new bottle let's open up the network tab just to make sure it's firing correctly too okay so we've got our delete that was good you can see the ui was updated as well and then we can check our state and we can see that um there's only four in our list now which is what we want if we can still add a new one so new event goes at the bottom let's delete the 30 milliliter bottle great that works nice uh okay cool so the next thing why don't we uh set up a way to edit this so let's say put 50 and uh she actually did uh was super hungry and actually had a hundred so flip over and what we're gonna do for this is we're gonna uh we're gonna set up a piece of state that's gonna contain the we'll call it the current event id and we're going to use that information to dynamically update our ui so that when we want to edit an event it'll turn into like a little kind of mini input form sort of thing and if we're not in edit mode then it'll just be our standard list item so we can do const event id and uh set event id and we'll instantiate it uh with a value of null and then we can create our edit method so we'll do const handle edit and it's going to take in an event because what we're going to do is we're going to set the event id and then we're also going to update our description field so we'll have like a little and what we can do actually here is so we have our description which is for the uh the main form what we're going to do as well is we're going to like essentially turn this into its own little input and so we need to grab the value of that description as well but we don't want them to be using the same piece of state so we'll create uh like a kind of a one-off piece of state for any um for any edit state handling so let me just duplicate this and we'll do edit description and set edit description and so our handle edit uh what it's going to do is set the current what is it set event id to the event.id it's being passed in we're not this is not hooked up yet but it will be it'll be similar to our handle delete where we're passing in something but in this case we're passing in the whole event and then we're going to set our edit description equal to the event dot description okay so now we need a way to toggle back and forth between edit and uh read mode so let's set up a little bit of logic so we can actually grab this return i'm going to cut it and we'll say that if the event id which is the event id in state if the event id that that has been set is equal to the event id of the um like the individual list item if that's true then that means we want to edit it so what we'll do is we'll do a form our form is going to have an input and actually let me do uh just so i can dump this off somewhere we'll return this list item and if we need to make an update which we do for the edit uh we'll we'll do that so we have our if else so inside of our form we can use the same on submit handler with some updates to that method which we'll do in a second so we'll handle submit and then our key for the form is going to be the to do dot id or sorry keep saying to do sorry um so our event.id and then our input is actually going to be almost identical to this so let's do uh our input and while we're at it let's add a placeholder so our placeholder could be um describe the event in this case we don't need a placeholder we're going to just populate it with the current description so our value here though is going to be the edit description and so our name and id can update as well to edit description uh for this um we can use our handle change and we can make this a little bit more sophisticated but let's just do this so um our handle change and doing it in line like this it almost uh so what we're gonna we can pass in like um so we'll have our event and then we'll have the field that we want to update so in this case it'll be edit and in this case it'll be description or you could do like true false if it's uh if it's just two fields like this there's just one way to do it it's kind of a quick way of getting it set up and then we can do um we can take in our two arguments and we can do e and edit or we can do a field and we can do if field is equal to edit then we can set our edit description equal to target.value otherwise we can set our description to e.target.value um we could set this up in different ways too where we're like dynamically you can there's ways of um utilizing the name field as well to um more programmatically edit or uh kind of utilize this uh a handle change method like this for multiple fields for this we'll just leave it like this um and uh that could be something that you uh pursue and add on to later if you want to take this application a little bit further so we have our handle edit method we need to continue updating our uh events list down here so the last thing we need is a button but we also need to wrap this in a return block so we can do return and then uh so we have our form our input and we need our our button so the button is going to be similar to the to our regular description one where we have type equals submit and then we need a way to to activate the edit mode so what we'll do is above our little delete x button we'll just create a button that says edit and then when we click it we will call our handle edit method so handle edit and we're going to pass in our full event so that we can grab the idea in the description so this should be good the last thing that we need to do before this actually works is update our submit method so in our submit what we can do is inside of this try block i'm going to cut what we've got currently and i'm going to say if edit description so if right now edit description is a falsy value so it's an empty string so as it stands if edit description this would not be hit because edit description is falsy but if it does have a value if we populate it which we would do with our handle edit when we're setting edit description equal to our event.description then this little block would be true and if it's true what we can do is we can say const data is equal to await axios dot put and by the way i'm getting all these methods from our back end which we set up in app.pi where we've got these so we have our endpoints we have our methods right so this is our editing event where we're going to hit events slash id as a put so that's that's just where it's aligning where i'm getting these these methods from so axios.put and we're going to use our template literal where we'll have a base url slash events slash uh and then this will be our event id so remember this event id is being set in our handle edit method so when we click on edit all this is doing is and maybe this would be better named as like handle or like toggle edit um but what this is doing and actually let's do that so let's do toggle edit to make it a little bit more clear as to what it's actually doing because it's not handling the editing it's just making it so that we can edit so toggle edit it's setting our event id and it's setting our description so we have access to that event id now we don't need to pass it in and then similar to our regular handle submit we'll pass in a description but in this case it'll be our edit description our updated event is going to be equal to data.data.event or description excuse me and then our updated list is going to be equal to events dot map and for each event oh and again this is events list for each event if the event dot id is equal to the the event id that we have in state then we'll return the event equal to uh we'll basically set our event um equal to the event that's being passed in will update it to equal the uh updated event otherwise we'll just return the event so basically what this is doing is it's transforming our uh it's updating our ui so again we don't have to make another network request where the event that's being mapped over is now equal to that updated event which we uh which we submitted and now we're just creating a new list that's going to have our updated information on the front end so our updated list we have that and then all we need to do is set our event list equal to the updated uh list so we have that our if block otherwise we're just using our submit for a new event and then uh in doing this we also want to make sure that our um event id and edit description fields are reset so we can actually cut this description and if we're in the try block that means that we've been successful so we can clear out our description we can set our edit description uh to an empty string and we can set our event id back to null so we should be good to go at this point let's go ahead and flip back over and we can see our edit and delete buttons and let's say that we want to change this from 50 to 100 so if i hit edit you can see the value got the value stayed the same so now the value of this input is 50 milliliters if i say 100 we take a look at the network tab let's clear this all out and hit submit okay we got an error event dot id is undefined so let's take a look on line 92 okay so the issue was uh i put description but really what i want to do since we're what ended up happening so here's our response so the the the um the request is fine it's just uh how i uh set up the updated list of events so you can see that we in our response to this put request we get an event object and so what we need to do here is in our handle submit if we have edit description what we want to do is our updated event is not data.datadescription it's data.data.event so we want to grab that event object and then hit save so now if we flip back over let's just refresh this to make sure it's good 50 milliliter bottle we hit edit now that individual event is editable we do 100 we just clear this and submit and now we get our 100 milliliter bottle updated in the ui you can see our put request was successful we get all of our return information and if we were to refresh the page we would get so notice it's just our put request going through there's not an additional get but now if we refresh you can see our get request and our 100 milliliter bottle so that data does persist in our database sweet so we've successfully incorporated all of our event operations so we've we can create a new event we can edit an event we should have a cancel button here as well uh we can add that to uh our our input and just hit submit for now um we can delete so create we can read them we can update and can we can delete them just to make this a little bit more uh useful for informational purposes and just to show how date fns can be incorporated in this so we have our created at time stamps what we can do is we've imported format at the top and in our list items we can let's go down to our list item so in our list item we have the event.description but what we want to do is um in addition to that we can do our uh event dot created at but we can format it using date fns so what we're going to do is we're going to do format and then we're going to create a new date object using the created at time stamp so we're going to format it we're going to use the format handler from datefns we're going to create a new uh a date instance and we're going to pass in the created at time stamp and then the second argument is going to be so after the the new date the second argument is going to be the format and so we can do like month day then uh let's do a little and um we can add in like a little space there so now we should see our time stamp and so we have the am pm as well uh the last thing that we can do we should be able to sort these these should be coming in sorted and let's just double check so we can sort them on we should be able to sort them on the back end but let's see so one three six seven let's just check our components here so in our app let's see we have created at and the id is one okay so if we flip back over uh to our application uh our app.pi file excuse me and in our get we're ordering by event id and instead what we can do is we can say event dot created at and then if we flip back over let's see if we get that just with refreshing cool so that was a just a quick back end change so again we we just flipped the order by um property to use created at rather than id uh and now we get them in order sweet so we've got it front to back flask postgres and react we've got a very simple application but we can create read update and delete events uh and now you've got them talking to each other your front end and back end so thanks for hanging out and that's it for this video appreciate your time and have a good one
Info
Channel: Chris DeSilva
Views: 13,578
Rating: undefined out of 5
Keywords:
Id: EAcD5ueqvHQ
Channel Id: undefined
Length: 43min 20sec (2600 seconds)
Published: Sun Dec 05 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.