React Native Web Full App Tutorial - Build a Workout App for iOS, Android, and Web

freeCodeCamp.org · Beginner ·🌐 Frontend Engineering ·7y ago
Skills: React90%

Key Takeaways

Builds a workout app for iOS, Android, and web using React Native, Mobx, Typescript, and React Navigation

Full Transcript

welcome to the beginning of my react native web series in this series we're going to be building out a workout app specifically we're going to be modeling it after this program called strong lifts they have an app and we're going to be implementing some of the functionality for this app specifically we're going to go over keeping track of your workout and then the history of your workout and have an app that does that now we're going to be building this with react native web so what this means is at the end of this we should have not only a website but also an ios and android app that does it for us and we should only be having one code base or at least the majority of it's going to be a single code base now here are the other things that we're going to be using to build out this app secondly we're going to be using mobx for state management and then pairing with that we're going to be using typescript as the programming language we're going to be using react navigation to be able to change pages in both the app or change pages in the website and we're going to be using react hooks for the entire thing and then we're going to be just working with the front end for this and so we're going to be storing data in local storage or async storage on the phone so that way we can persist the workout data as the user uses the app or uses the website and doesn't lose it after they come back to it all right so in this video we're going to set up our react native web project now to do this you can do kind of a multitude of boilerplates but i'm going to be doing create react app to start off with and then we're going to be you're free to choose a different one if you want to and then we're going to be possibly using our own webpack config later if we need to change some of the config and then we're going to basically just be going through the client side rendering portion of the react native web app uh read me for now so i went ahead and ready set up the react native or the create react app project right here so if you want to do the same you just go and run yarn create and you run react app and then whatever you want to name it and then i did dash dash typescript to make this a typescript project and then after that we should see some typescript files in the source and i just have this open in vs code right now so the first thing that i want to do is i want to add react native to this project so i'm going to say yarn add and i'm going to install react native react native web and then this package called react art or react art which react native web needs now i'm trying something new for this series you'll notice i have versions at the end of all of these the reason for that is i'm going to be trying these exact versions so you can follow along with me and hopefully as the series progresses there won't be any changes with you installing a later version of the package also the other thing you're going to want to make sure you install react native .55 because if we take a look at the react native web documentation it's compatible with that version and not higher so we'll go ahead and install these three packages and then we're going to install the types for react native that way we have type definitions when we use typescript with it so we're going to say yarn add as a dev dependency and we're going to be adding react native and i can just bring that up so you can see it better and again i'm installing the types at version .55 just so it matches up so after we have installed those things we're ready to basically take out some things from the create react app which we just do not need so for example we do not need the svg index.css app or apptest or apps.css so i'm just gonna go ahead and just delete those now and then in the index.tsx file i'm gonna go ahead and delete this line right here and then we're going to paste in this client-side rendering code right here and so now we're just going to remove this react dom.render instead of us saying reactdom.render we're just going to be using this app register now notice uh ours is called root here this get element by id so we're just gonna rename this to root right here as well and the way that we're gonna go throughout the series is i think we're going to build out react native web or at least the website and then at the end we'll get it working with the app or maybe in the middle we'll spin up also the app and make sure that it's working but we're going to primarily develop this from a the website point of view and basically the process of doing this is we're actually going to just be writing all our code uh using react native import so you'll notice we've imported from react native here we're going to be importing from react native the entire time through our code all right so i'm gonna go ahead and save this and it's going to remove those dead imports at the top i have it so a vs code setting so it does that for me if you want to turn that on you can go to preferences settings and if you come click on the brackets over here you can see the bracket versions of your settings and i believe one of them i have organize imports yeah so this editor.code actions on save i have it automatically running organize imports so you're going to see that throughout the series happening so now that we have this initialized in our index.tsx we want to just go into our app itself and convert it to using react components or react native components so that's just app.tsx right over here and we're not going to be using classes we're going to be using function components and hooks so i'm going to say const app and here we're just going to say return and also the other thing i want to mention is probably throughout this i'm going to be using some different shortcuts so i'm going to be posting my vs code settings below if you want to get these as well so one of them i have is called rnss so this is going to create style sheets for me so we're going to be using style sheets from react native to do this so these are little snippets and also i have rh for react hook and so this is going to spit out a snippet that looks like this and so here i can say uh the name my component app and this one doesn't take any props so i can just say say it like that and now i can put whatever stuff i want here anyway i'm gonna get delete all this stuff we don't need any of that code right there and i can get rid of all this stuff here and basically we can empty the file and just have this and we don't need to export this so now we're going to actually be using a react native components here so i'm going to say view and then we're going to say text and we're going to say hello from react native web and of course we need to import all these and i can i just hit command and then period this is another one you're going to see me do throughout the series to import things i can either import just this view or import all missing imports the other thing you'll see me do is if i have my cursor here i can hit command and space to auto complete get this menu up both of those i'm going to be constantly doing throughout the series so it's good to add those to your repertoire as well um and yeah the text we want to also import i just did command period and it doesn't look like it's slaying me import it so usually i'll hit command space to uh sorry control space and i'll bring it up and you can see i want to auto import from react native we'll hit enter all right so this is what the start of our application is going to look like if i come back over here we need to start the server up say yarn start and then when this boots up we can go to localhost 3000 and it's going to actually render the view and the text and so the thing with create react app is underneath the hood what it's going to do is it's going to change react native to react native web and it's going to be using those components and then react native web turns the view component into divs and i guess the text component maybe also into divs but anyway we can see the text right here show up we can even inspect this and see what the heck it created for us you'll notice with react native web it spits out a whole bunch of classes for us that's an interesting thing i noticed but anyway that's kind of your introduction to react native web of how to set it up recap of what we did is we installed three packages react art react native and react native web and then inside our index.tx we initialized our app using this bit of code that we got from the readme instead of the react-dom and then in our app we're just going to go ahead and continue to flush out this thing using react native components so before we go any farther i want to make sure we can get react native setup with react hooks so that's we're going to be doing in today's video and start off with we're going to be using the react native cli now usually when i start a react native project i'll usually opt for expo just because the development experience is a lot better and you can start up the emulator and build the application a lot faster but as of today or currently they do not support react hooks at least i don't believe they do so we're just going to be using the react native cli for this so to do so we are going to first install it and we're going to install it globally by running this command npm i-g and i already have it installed globally so i'm just going to interrupt it next thing we're going to do is run the cli to create a project in react native so we're building the project in typescript so we're going to follow this guide right here and we're just going to run this command right here and i've already done this initialized a my awesome project and that's what i have open vs code right here so after that the first thing i want to do is if we look at our package.json you'll notice that they have two dependencies react and react native so we want to set up hooks in this project so we're going to need the latest version of react or at least react 16.8 and then for react native we're going to need version 59 to work so we're going to install both of those so we're going to say npmi and install react at version 16.8.2 and react native at 0.59 and this is currently a release candidate so that's why there's this dash rca so we're going to go ahead and install that and then especially with react native you might have saw or mentioned last video that with react native web it's only compatible with .55 and we're currently using we just installed five nine to use in this particular project so this is what i'm going to attempt and we'll see how well it works is i'm going to be using 5 9 in the react native project this one and then our web project we're going to be sharing the same components but we'll see if we can get it working the components even though we're not we're gonna try not to rely on any react native five nine features that would break the react native web project but we'll see how that goes um anyway so we got this uh installed so we can go to the app.tsx so this is what's currently being rendered if we were to start the app right now i'm gonna just delete the app.js because we do not need it if you click on it you'll notice it has the flow version if you want to use flow but we're going to be using typescript all right so we're just going to write out a simple hook to make sure this works so i'm going to say down here just export defaults app and then i'm going to convert this into a function so i'm going to say const app and then this is going to just return and then i'm going to just copy the view and then we're going to say const use state and we're just going to create a little counter to make sure it works so here i'm going to say count and set count and then here i'm going to display the current oops current value of count and then below that we're going to render a react native button we're going to say increment and then whenever you press this we're just going to say set count is equal to count one and we're going to give that a save we don't really need the props here and now if we go to our package.json we want to run this project so we can start the cli or the packager by running yarn start or npm start the next thing that we have to do is actually start the emulator itself so i'm going to be running the ios emulator so what i'm going to do is i'm going to say ios here and i'm going to say react native run ios now for those of you that are on a windows computer you're going to need to use android and you're going to need to have android studio installed and have an emulator created and when you have both those things you can create an android script here and just say run android and you want to make sure i believe your android emulator needs to be running when you run this command but if for the ios one it'll automatically stir it up for you so we're going to say npm run ios and uh just a heads up this will probably take a few minutes to actually build this on the emulator and get it all working and then we'll see our application and make sure it works so mine finished building and i can see the app starting up here now if you don't see it started up what should happen is if you go to just the screen with all the apps there should be a new icon it should say my awesome project or whatever you named your project you can just open that up to see it so if we go ahead and click this we can see it's incrementing the state so hooks are indeed working with react native right now so where we're going to go from here is we can now have our react native project set up and we also have our react project setup so the next thing is is we're going to set up a mono repo so that way we can create basically that one code base that we're sharing with our react native setup and with our react setup and basically that one module or package that we're going to share between both of them and we'll set that up so we are now going to set up a mono repo and the reason we are doing this so it's easy to share the code between the react and the react native project that we set up already now i just did a step before i started this video i created a folder which i just called my monorepo and then i took the two folders or projects that we worked on in the last two videos and put them in here so i copied the my awesome project into this folder and i also copied the react native web series and this reaction of web series is just what i called the project that we created with create react app so i'm going to be starting from here and the first thing that we're going to do is set up yarn workspaces so in my mono repo once you have these copied over we're going to create a folder called packages and then i'm going to rename my awesome project to app and that's where the react native code is going to go and then i'm going to rename this to web and i'm going to put that in packages so here's what our file structure looks like right now and then next i'm going to say npm i dash y or init slash y to initialize a repo here or a package.json i mean and then to actually make it into a yarn workspace we need to say at the top here private is equal to true and we're going to say i'll just add this at the bottom workspaces and then here's where we specify what our workspaces are we're going to say packages star so what that means is any uh thing that we add in the packages folder is going to be considered a package that yarn workspaces are going to see and be able to do stuff with so now if i were to run yarn right now it should install all the dev dependencies for everything and i'm just going to real quickly just remove oh perfect area have this up all the node modules and all these packages so remove an app and remove it in web and i can do it with this command so i'm saying remove rf packages and then i'm saying doesn't matter what package you can do that with the star command and then remove node modules you could also just go into each package and remove it there's only two right now that's a little shortcut for you all right so i deleted that i'm just gonna go ahead and run yarn and i'll let this run in the background uh because it's gonna probably take a few minutes to like install that stuff so next thing that we're going to do is we're going to create a new folder which we're going to call common so common is basically where we're going to start we're going to be developing stuff most of the time so this is where the one code base is going to live and then both the app and the web are going to use this one code base so i'm going to go inside of packages common and we're going to just initialize this with a package.json as well now i'm going to give this a let's refresh there we go i'm going to give this a name i'm just going to call mine wow so whenever you deal with yarn workspaces or monorepos in general usually you'll have the name of your monorepo and you'll say at the name of your monorepo slash the name of the individual package this case i'm just naming my monorepo wow and that's what i'm going to put here next up we're going to create a source folder and inside of there i'm going to say index.tsx um and here i'm just going to paste just a demo app at the one that we created so if i go to app app.tsx i'm just going to copy the app that we created so copy this paste it in and of course we need to install uh react and react native and stuff in here so let me just make sure this is finished running it is um cool so in here i'm gonna say yarn add we're gonna add react native and react and we're gonna add react at 16.8.2 all right so when that is done we're then going to install the dev dependencies for react native and then we're also going to install the typescript and then we're going to have to add a ts config to this so let's do that and i am installing this as typescript 3.3.3 and then this is just the latest types for react native even though we are using a later version of react native itself this is kind of the latest types all right so uh now we can say here i can just import this all from react native or whatnot it's taking a second to load instead of me manually importing this i'm gonna just give it a second and we're going to create a ts config all right so in our ts config i'm just going to copy what we have in the web and then we're going to make a few changes so for this we're going to say allow js we're going to remove that we don't want to allow js instead of isolated modules we're going to say declaration is true and when we set declarations to true we build the module what's going to happen is it's going to have typescript declaration files in it which is what we want and here we're going to say gsx is going to be react and then no emit i'm going to get rid of that and then module i believe we need to change this to common js and then i'm going to say in out directory i'm going to say is dist and i believe that's all the changes that we need to make to this file but when we build a project and then try to use it we'll see if we have any problems all right so this should be good loading it is so i'm just going to say command period and import everything in and it looks like text didn't get imported for some reason so control space and we'll import that and did stylesheet get added nope there we go instead of export default i'm just going to export it like that and that looks pretty good in the pangs.json we are going to say ts tsc and i'm going to rename this to build and what this does is this runs the typescript compiler and it's going to compile our code so if i come here say yarn builds and it's going to look in the source folder build it and we can see the dist so a couple things if you know this work correctly is in your dist folder you should see an index.d.t.s should just look like this i guess and then in your index.js it should look like this and you'll notice that there's not jsx in here right so it does not look like this where there's brackets and stuff that's jsx it looks like this and we're saying create element in here so that's important um yup so that is pretty much all we need to do in common i believe so next we want to basically use this code base and both of these projects so today we're going to start by adding it to the web so to do that we're going to head over to the webspace.json and we need to first add the common package as a dependency so i usually just come in here and i say wow common and then we're gonna set the version of it and if we come to common package.json it'll tell us the version is just 1.0 um oh the strong one so we're going to put that there and then after we add that we just need to say yarn so we're gonna cd over to the web and that's just going to add uh this common package in here uh and now if i go to my app.tsx instead of just saying hello from react native web what i'm going to do is delete this app and i'm just going to export the app which we get from that package which we said is wow common all right um and let's see if uh currently cannot find it uh i'm not sure i'm i just hit command and then p or if you do command capital p it'll open this little window i'm going to restart the typescript server to see if it actually can find the module the other thing you can do to double check is if i do an ls node modules i'm able to see whether or not it was added and we can see at wow is not there so that means it didn't get added for some reason so i either messed something up uh or it didn't get added for whatever reason so i'm just going to say yarn again or you know what i'm just going to remove the node modules all together and just have yarn run again and see if it gets added this time oh you know what we forgot one important step that's why it's not working so if we go back to our common package.json if we look at this main we need to specify where the main file is so for us it's going to be inside of dist and then index.js so let's add that real quick all right so now we're going to just i don't know if we need to re-yarn if i go back to the app oh cool so you notice how it just went from red to orange i don't know if you're watching right there it also is no longer an error here so it was able to find this file now so we're going to say yarn start um and we're going to get this error about skip pre-fight check um or that we did some things wrong and it's going to tell us some things are wrong basically we're trying to access a module outside and maybe we're doing some other stuff wrong but we can just add this skip preflight check to the beginning and everything will work so let's go ahead and do that so skip pre-flight check is true now for those of you guys that are on windows to get this to work we can add cross m in front of this so i'm now going to add cross m as well and it doesn't matter what uh version of cross mv you get it should probably work and that just makes this work on windows all right so let's do yarn start again um and if this works correctly what happens when this starts up is we should see this little app counter that we have where we can click on it and it's going to increment the count using hooks in our website so it looks like no crashes come over here we see our little welcome to react native can increment and that's our hooks working so awesome so what we just set up is a common package which we are now using in the website so getting this to work with react native is also a little tricky so that's what we're going to save to the next video and so we're going to import basically this common package or get the common package working with the app as well and so what's going to happen is in the future we're just going to be coding in this common folder and then both the web and the app is going to get this code and should basically be building the app and the website in parallel now i just want to go over real quick a few things that is important about what we set up because this can be kind of tricky to get working so if it is not working for you these are the few things that you want to check so you notice i was coming over here and i was saying ls no modules and couldn't find it i think what i was doing wrong about that is one it should be in the root folder and there it is so if i do ls dot dot dot in the root directory or the root mono root mono repo we can see the wow folder and we can see comments so that is important to be able to see so the thing is again this was important we we missed this at first you want to make sure that you have index or this dist this main is pointing at an actual file that exists and that's pointing at disk index.js one other thing i want to add real quick is i'm going to add this thing called rimraf so this is going to delete the build folder or this disk folder every time we build that way we don't have stale data in there so i'm going to say remraftdist and we're going to build okay so i'm going to cd back over to common and uh yarn add as deficiency rimraf and this doesn't really matter what version either and so what that's going to do is it's just going to delete the folder and then it's going to build it each time and if we do yarn build nothing will really change but that just helps get consistent builds sometimes i get funky stuff when i don't do that the other thing is with the ts config there's a couple important things make sure the jsx is set to react make sure that the module is commonjs and the last one is declaration is set to true and so when you build stuff you get a nice dist that has the right output that we want and notice we're saying include source here that's how we know it knows to build the source folder right there as well and that's pretty much the key parts of getting this to work i think and then after that we just add of course uh this to our package.json the wow package or the common wow package we're going to use this common package that we created and use it in our app package which is based on react native now getting yarn workspaces and importing from our workspaces is actually a little tricky with react native and we're gonna see why that is in a couple minutes as we kind of run into some of these issues and we'll deal with some of the workarounds to get it to work so to start off though we are going to just install or add the dependency to our package.json in our react native project so i'm going to say at wow common that's just what i named it and i'm going to put version 0 here and then i can go to the i'm right in the packages app right here and i have yarn to install that um after that in the app.tsx i'm gonna just replace all this code that we have here with the app so i'm gonna delete this delete this delete this and then the app is going to be coming from that common package and then here if i just say app we can have this is what we want to render now uh if we tried just starting up the application right now we'd actually get an error we can try that if you want so we can say yarn start and it's going to say cannot find module now if we go to our package.json we can see why that is so it's trying to start the react native cli and you'll notice the path it's looking for node modules and then the react native one and if we just do an ls to see if that exists react native we'll actually see that the file does not exist or the directory does not exist and the reason for that is we're using a yarn workspace and so how yarn workspaces work is they hoist up the modules so what that means is it's actually sitting in our root directory so if we do an ls and we go up two directories into that node modules and we look for the react native package you'll notice we will find it that's because it was hoisted up so we can avoid this problem because we basically want it in this current directly current directory we could lift it up if we wanted to but i'm going to say no hoist so this is a trick that you can use with yarn workspaces and how it works is we can specify either in the root directory we could use that or in the child directory which we're going to be using no hoist on the react native package so i'm going to copy this and i'm going to paste it in my dev dependencies or sorry not my dev dependencies but in the package.json at the bottom and i'll link a link to this article this kind of goes more in depth about how no hoist works but basically what's going to happen is the react native dependency instead of being in the root node modules it's going to come down to the node modules that is in the app now whenever i add a change like that like i just added the no hoist option here i like to just destroy the node modules and reinstall them because usually stuff gets messed up in the middle also i just saw this was being unsaved i'm just going to save all right there all right so i'm going to do remove um and i'm going to remove rf both the node modules that's in this current directory and also just the route as well just to be safe sometimes stuff gets messed up now the next problem we're going to hit is after we get this it's going to be able to start up okay but what happens with yarn workspaces is to be able to access this common package and to be able to make changes to the common package and not having to do a yarn install every time is they use sim links now one of the downsides of react native or one thing that doesn't work with react native very well right now is sim links so what we're going to have to do is work around it so one option to work around it and that worked out real quick we'll talk about how we're going to handle sim links in a second let's just look if our node modules worked so if i do an ls on this node modules slash react native you'll notice it's now here so if i were to do a yarn start it should indeed start the packager now the other thing i just want to mention is i have my application up and running over here or my simulator and if i try to reload this right now it should have a problem yeah perfect well not perfect but here's the error at wow common does not exist in the haste module map so this is where it can't basically get the sim link that we're using for that now uh one thing i want to mention real quick is uh to start up my simulator over there i just did uh yarn ios which ran uh this over here um let's start up the simulator and the other thing is when i was starting it up because i moved this into a different folder when we were setting up the workspace there's this ios build folder right here that has a basically cached version of the build and it had the relative directories all messed up so i had to delete this build folder to get that to work so you may have to do the same thing if you were on mac i'm not sure if there's equivalent for android doesn't look like it all right so uh so we started that we need to handle this next error now i'm not sure the best way to handle sim links in react native right now i'm not sure if there's a standard way because the default bundler that comes with react native i don't believe works with it and there's a ton of open issues about it so hopefully that'll be fixed soon but one way that's super easy to fix it is this this one library called wml and basically what this does is we can just specify a directory so for us we're going to specify the common directory and it's going to basically copy over the files every time we make a change so we're going to be using that so if you don't have this already installed on your computer you're just going to run npm install and it's going to install globally so after that what we're going to do is uh control see this is we're going to say add and we're going to run this command right here so we're gonna go up a directory and get the common folder and then we're gonna put it into our node modules at wow common so you'll notice here this is just the name of the package and here's where the local directory is all right so if i do add i'm going to say yes ignore node modules and then what i can do is wml start so now what's going to happen is anytime i make a change in the common folder over there it's going to copy over all the files and where it's going to copy is that node modules slash wow if we take a look at that we can see funny enough it looks like our app is here i'm not sure why that's there slash common and we can see our code is there now uh i don't actually want uh it kind of looked pink there and i don't want it to be pink uh because that usually means it's a sim link but uh let's just see if this fixed it so uh yarn start and if it didn't i'm just going to delete it and then recreate it so let's reload this um yeah see i didn't think it would and i'm just going to let's do an ls on it again just to make sure um okay when i do an ls here it showed it like that but if i didn't ls here oh this is because i'm in the root directory that was just my bad all right let's come back over here so one thing i notice about the air is it's coming from react or it's coming from not being able to find the module react so what we can do is we can say no hoist on react as well as react native and that should be able to find it so i'm going to just copy paste this and i'm going to say react here instead of react native give that a save and then i'm just going to remove the node modules and the parent reason being if i remove them locally it's going to destroy kind of our sim link setup or our wml setup so i'm just going to say remove the root one and do yarn and that should add it for us and then when this is done what we can do to double check this works is again we can just do an ls on the node modules and make sure that it's all there another thing is to make sure your wl or wml thing is working is you can go to uh packages app and if we do an ls there on common uh oh it's mine oh i guess it deleted mine even though i didn't want to delete all right we can just restart it so ctrl c and we'll restart that and let's come back over here all right so it exists and if i go into dist you should be able to see the index.js that's all good because this is what we're actually importing is that index.js from the dist folder so you want to make sure that's there and now we should have a node modules react it should probably be done loading yeah so i'm going to come back and just say yarn start and start the packager and then get this running all right cool so that looks like it's able to load down and we can increment so it is working so as you can see it's a little tricky to get this set up but the gist of it is we had to know hoists and things so bring some modules down so in our case we had to do react native and react and then after that the other tricky part is making sure that the packages that we're using are sim linked or in this case we didn't want them sim linked so we had to bring them over by using wml and to do that we said add and then we say start which actually moves them over now whenever we make changes to the comment it should move it over so we don't need to do anything there as long as we have this up and running the other thing is if we were to add more packages we wanted to depend on we'd have to wml add now there are some other ways to achieve this same thing i believe in the past i've played around with uh i believe it's called like react native config or something where you can kind of get it i don't know if that solves the sim link problem or if it solves the no hoist problem but one of those but it can be a little harder to set up where this is not too bad to set up so i figured we'd start here and if we run into more problems we can investigate that later and then the only other thing is as we program stuff in the future we're going to be basically just doing stuff in the common folder and then the app should be getting the updates and the web should be getting the updates at the same time and i'm pretty much just going to focus on what it looks like on the web just because it's a lot easier to get set up and to also just view it and watch the renders in real time versus react native we're going to be going over how you can use mobx with react hooks to start off we're going to install two libraries in the common package the first one is going to be mobx at version 5.9 and then we're going to be using mobx react light at version 1.01 and this library is going to allow us to actually get it working with hooks so we're go ahead and install that and for those of you that are not familiar with mobx what we're going to be using it for is state so it is a state management library now to start off we're going to be inside our common package i'm going to go to source and create a new file i'm going to create a folder outside which i'm going to call stores and we're going to say counter store dot ts so here i'm going to say class counter store and i'm just going to close that and we're going to have a single field which i'm going to call count and it's going to have a default value of 0. now i want to make this field observable so we can do that with mobx by saying observable and we're going to import that and that's coming from mobex now it's going to complain about this if we hover over you can see tells us we do not have experimental decorators turned on so we can go over to our ts config and turn that on and so here we're going to say decorator it's going to be this experimental decorators set to true if i give that a save and i come back over here it should no longer be complaining about this now and i'm going to say export const and we're going to say counter store context and we're going to say create context and that's coming from react and then we're going to say new counter store and give that a save now this counter store context is what we're going to use in our components and then we can basically interact with the store that way so now in our index.ts we had a basic example before where we were using use state to store the state of a counter and then we were incrementing it so now we're going to start by making this work with mob x we're going to start by wrapping it with an observer and we're going to just wrap the entire function there and now observer is coming from that other package we installed so that's mobx react light observer and then here instead of using use state we're going to say const counter store is equal to use context so we're using the use context hook and then we're going to pass in the counter store context that we created so now what i can do is i can say calendar store dot count to display the count and then when i press on the button i can say counter counterstore dot count and then we can just directly mutate it by incrementing it so cool so now i want to see this and see if it works so to start off i have my server already running for the website so i have that up and i'm just going to compile the code here so i'm going to go to the package.json and i'm going to add a new flag that'll make this a little easier called watch and so we're going to say ts tsc and we're gonna say dash watch and so what's gonna happen is when we uh run this so yarn watch it's going to compile our code and watch for any changes we make and real recompile it all right so here is our website just give this a refresh and then if we increment you'll notice it worked just the same as it did before um so pretty cool and uh mobx looks pretty sweet being able to just mutate it like that is pretty simple i like that so of course we're going to be using mobx for the state management for our application so we're going to be using it to store basically the state for working out or for workouts so we're going to start by creating a new store today and i'm gonna call it the workout store and here i'm gonna say class workout store and today we're just gonna map out kind of a few different things that we're gonna store in this so there's basically four different uh or five different exercises that this workout uses so we're going to store that all in the store and we're also going to start off by kind of hard-coding things and then we're going to go back later and possibly make this generic and work with say any set of exercises so the four exercises is squat or five exercises is squat and what i'm going to do is i'm going to call this current squat and when i say current squat this is what it stands for is kind of like how much are you currently squatting and this is going to be a number so for example you may be squatting 500 pounds or 100 pounds and we're going to track that in this variable let's see why it's unhappy oh has no initializer um let's turn that setting off for now uh [Music] initializer strict property initializers is i think what we need just turn off to be able to get rid of that warning say false and cool and then we're going to say squat bench press overhead press overhead press and i guess let's be consistent i said press there do press there deadlift and that'll be a number two and then lastly is the barbell row all right so these are the five exercises and again i've kind of hard coded it here we could also go with the approach where we kind of have this in an array but i'm going to start dead simple and then we're going to kind of refactor things out and make it more dynamic as we go we also need to know so how the workout works is we're going to have two different days like a a day and a b day and so we need to know what our last day was because we do a different exercise on each day so for example i don't know maybe on the a day you do squat bench deadlift and on the b day you do squat overhead barbell something like that so we're going to say last workout type and we're going to make that a a union so we're going to say workout type is equal is either an a day or a b day and so that's going to be of that type workout type or why don't we call this workout day that makes more sense either an a day or a b day so we're going to say last workout day well i don't think last workout day really makes sense we'll say last workout type is fine and uh let's make that a lowercase oh i suppose um and then the last thing that i can think of at least to start off with is we want to know the history of what lifts that you've done and so we can keep track of that and the way i want to keep track of it is kind of a dictionary that way we can keep track of in the key being the date so what i'm thinking is create an interface which we're going to call history called workout history not to confuse it with any other type of history like browser history or something so the key i'm thinking is going to be a string representing the date so we're going to say key of string and here i don't think i need to say key i like to say key and then the value of this is going to be i guess an array and the array is going to have basically the values for that day so here i'm going to call this the movement or the exercise is a better name exercise is a string and then the value which is a number so for example uh what that might look like is i'm thinking something like this so on the 18th so uh let's see what month is it i don't know like o2 18 2019 is going to be the key and then the value is going to be array that looks like this and then the exercise might be squat and then the value might be like 90. so this day you squatted 90 pounds and then right maybe you also did bench press that day and did that for a hundred pounds so this is what i'm thinking the data structure to be and we may improve this data structure a little bit and add more fields to this later on but this is what i'm thinking for the start of it anyway this is kind of the start of our store uh let's go ahead and just add the type real quick um and then the next videos we're going to continue kind of working on this store and start adding some components and start rendering some things for it but before we end this video let's just export this so export cons workout store context is equal to create context new workout store so i was wanting to go over navigation today specifically adding a button here that was like start workout and then we'd be transitioning to a new screen and to do that i was planning on using react navigation because i saw they have a react native web version and it works really nice for a react native so it'd be nice to be able to use it but after i tried out the example i saw the reaction of web one was kind of just meh and i didn't see a great way to integrate it so we could have one kind of routes that would work for both the native and for the web i didn't see a great way to do that and they didn't have typescript types so i was like let's go check out how devhub does it to see how they were doing navigation and it turns out they actually have just a ternary operation and they have just two screens a login screen and a main screen and that's how they're picking and our application is not too complex so i figured we might as well do it in a similar manner and use mob x to keep the state and just kind of have a tern area where we switch which page we're displaying because react navigation at least for the web seems like it still has some time before it's production ready slash really a good choice so that's we're going to do in today's video so i have the app up earth website up and we're going to create a in the common package a new folder here and i'm going to call this routes actually i'm just going to create it as a file called routes.tsx and this is going to basically where i'm going to store it so i'm going to export cons routes and we're going to return null for now now i said we're going to store this in mobex so i'm going to create a new store which i'm going to say routers or i guess route routes store i don't know if that's the best name for it um then i'm going to come over here and just copy the counter example so route uh actually you know i like router store better just thinking about it let's go matches this better i guess well i guess i call that routes oh well uh so i'm going to say router store here router store context and then i'm going to say this is going to be a path and the default path i'm going to say is the home page which uh actually i'm going to call the home page the history page because i think we're going to store the workout history on the front page so i'm going to call that history and then actually not well so the history kind of implies like uh navigation history or route history so i don't want that to be confusing so that's just kind of what went through my brain with the naming convention right here um so you know what maybe we'll go back to home but i think i'll keep it for history for now um maybe i'll come and switch it later as you can see i'm not great with naming things um all right so we have this and so we're just gonna use this in our routes over here in the same manner that we use the counter context so we'll use that so this is going to be the router store use context router store context let's import use context and come back to our router store not router store we just need to use observer around this i was going to copy and paste but there's not really a good way to copy and paste it so we'll just let's do that and then we need to import this from the mobx lite so that is this one right here for a reason it doesn't auto-complete well for me at least when i do like uh control space uh just kidding it worked today so actually we're good to go and so what i'm thinking here is we'll just conditionally render stuff based on what the router store value is so if i go to i'm going to create a new folder now which i'm going to call modules inside of there i'm going to call create a history you know what yeah that's confusing let's just call it home no i'll call workout history there we go that's what i should really just do to make it super clear so we'll say work out history um and here i'm gonna say export const workout history and i should really one i already have a oh this should be tsx tsx uh i forgot i have the uh rh uh thing that i was gonna use this is my uh template they just create a react hook or a snippet so let's use that to just save us a little typing workout history uh and so the workout history is just going to say view text workout history page for now import all that import the text as well and we're going to have just empty props for now give that a save and then the other screen is going to be the current workout dot tsx and uh you know we could just copy what we have over here because we're gonna do the same thing and just rename it that'll be the fastest uh and i misspelled page but that is okay current workout page and let's rename that current workout page okay so let's just recap what we have so far i made a dummy component called current workout i created another dummy component called workout history and these are basically going to represent the pages of our application we have a mobx store that's going to store which page we're actually rendering and using this path and maybe path is not the best name really it should be like i guess say screen is the best name for it i suppose uh and then in routes over here this is what's going to display and you know what instead of routes we could really call it router i think that makes more sense because that's really what it's doing so what we're going to do here is basically decide which one we're going to render so here we can say router store dot screen is equal to workouts history and you know what i should make this uh this a type a union type and then we get auto completion so uh you can say route workout history is really the only route right now all right so now if i do that i think we should get auto completion here yeah so pretty cool you get auto completion on strings because it knows that the only possible type this can be is workout history so there we go so if it's equal to workout history we're gonna render the workout history screen otherwise we're gonna just render the current workout current workout page i just want to call it current workout not current workout page so let me get rid of that uh so we'll rename that there and then that's good there uh and looks like i need to import to react at the top uh so this router now is what's going to be uh rendered over here so uh we have all this junk and we're saying export const app now i'm just going to say export com actually we should just say export all from router actually that's not what i want to do i want to say so what i'm trying to decide is if i want to actually keep this container style and i think i do so i think i'm just going to get rid of all this stuff here and do this and so now we'll have router like that okay i think i like that so i'm gonna get rid of this we don't need an observer here and we can get rid of some of these styles all right so now what we're doing is we're rendering our app which just renders the router and then that router has these two screens right here so let's look at that so we have this it's his workout history page um and so now if i want to change pages we can add our observer um observer and then we can get access to the mobx state that we used or the router store and that allows us to say use context and we're going to say router store router store context and we're going to just add a button to transition so this is going to be like create workouts and actually on react native you say title so create workout like that and then we're gonna say on press and we're gonna say router store dot screen is equal to workout history oh you know what it can be now two possible screens so button react native is where import it from so let's go back to our screen over here so it can either be workout history or current workout so we're just going to transition this to current workouts give that a save uh so now if i click that it'll transition me to the current workout page and of course if i refresh it's going to take us back to the home page or the workout history page so cool and we can add a button back over here it says like go back or something which we'll do in the future and this is going to be basically how we're going to store or access the router state is we can just access it through the uh router store context that we created with mobx anyway so that's how we're going to be handling navigation it's just through this mobx store because one it's dead simple um and it will work and looks like it is you can actually use this in a real application and dev hub has had success with that anyway guys uh there's one last thing that i want to do before i end the video and that's just to make this style uh a slight change to this so i just want to make so this wraps or that this is kind of like phone size so if i right click and inspect i can click on this we can get what the size of like a phone is so for example we can get a large mobile phone is 425 pixels so i'm going to just set like this container to 425 pixels or i'm going to create a new one which i'm going to call a wrapper so style wrapper styles.wrapper and what my wrapper is going to do here is all it's going to say is the width is going to be 100 but it's going to have a max width of 425 reason why i'm doing this is because i don't want my content to just like stretch uh the entire screen as it gets really big and i kind of just want it to be centered right here at 425 and that be where it stays so that's the plan is to have like this little wrapper and i think i want the color i can't decide if i want this color in the center i think i do so i'm just going to move the background color to here and have it like that um the other thing that we need to do is you'll notice that the color doesn't extend the full screen if i hover over this we're not currently doing or we're not uh this is this content if we hover over you can see that blue it's not taking up the full screen there's actually something in the react uh native web documentation about this how we have to make the height 100 so we're going to do that real quick because uh that will be helpful so this spans the whole screen as well so to do that we actually need to touch some html so we're going to go just to the web public index.html and all we're going to do is we're going to add a few styles so we're going to say style height 100 is the first one we're going to add and we're just going to add that to both the html the body and the div because those are all the things that are uh not 100 right now uh so if we look at the html is now 100 body the div and now i think this we can set it as 100 i think now and then it'll be able to match also one thing i noticed when i was uh kind of digging around with this is the inspect tool's kind of broken with react native web or at least it's not as good you'll notice if i'm like looking at the styles of stuff it's kind of broken up a ton so like let's say i want to see what color this button is it's not really clear and everything's broken up into 100 properties so the inspect being able to inspect and basically replace the css and stuff is not exactly something you can do with react native web because of that and how many just classes they spit on to this but anyway that's just the side note that i noticed if we come back over here we can uh say this is has a height of 100 i think we're saying flex 1 so i'm not sure what else we need to add to make it i think that was the only things that i saw in the docs to make the height 100 um i guess we have to target this guy right here and set its height to 100 which is this is kind of the outermost div that we just did or the outermost view so i'm gonna go check the react native web uh docs in the next video we'll make sure this spans the entire page because we kind of want it to we're going to be building out this card as a component it's going to be keeping track of basically the current user's workout so for example as they're squatting they're going to be marking how many reps they did and keeping track of their sets with this now before we actually build this component out there's one thing that i want to do real quick when i left you last we wanted to fix the height of our application because right now it's not stretching to the very bottom and we can easily fix this by making two changes the first is in our public index.html we want to just come over here and uh this div which has an id of root we're gonna add a display flex on it and then after that in our index.tsx if we come back in our common package we're just going to say on our wrapper a flex of 1. and so what that's going to do now is uh this div is going to allow whatever content is in there to grow i'm in flex and then we said flex 1 to make it grow the wrapper grows and also the container grows and now it goes all the way down the screen so we're able to fix that all right so now we're going to get on to this component and start building this now before we actually start building this component i thought it'd be helpful to kind of go through how i look at this and what goes through my brain when i'm kind of like envisioning how to build this i know this is a little bit blurry but it'll do and we kind of get the general shape of everything so when i see something like this i actually kind of in my head break it up into a lot of different boxes because most layouts what i'll do is i'll break it up into big boxes and then smaller individual boxes and that's usually all layout is a bunch of boxes even though this may not even look that boxy so to start off the first thing that i kind of think about is like i see the edges right here and just the container itself i think about so the first thing i noticed is like it has rounded corners so we're gonna have to add a border radius to the container then i notice there's a little shadow so we're gonna have to add a box shadow for the container itself and then i kind of go into the content itself the first thing i notice is there's some natural splits so for example the content is kind of split in the middle here so we immediately see we're gonna have like a view on top which is going to be this portion and then we have a view on the bottom which is this portion itself that was like the first big split that i saw and so you can already imagine our container may display the flex direction maybe a column and we'll have this on top and this on the bottom and then we'll notice this is going to be a text field and if we look at this we'll basically see there's a little padding on the side here and there's a little padding on the side here and then basically there's a ton of space in between them right so i imagine we're going to do something like space between there's a justify content setting which basically spaces this and pushes all the space between the items so i imagine we're going to have a view here then we're going to have some text some text and then our view is going to say justify content space between and it's going to spread them like that and then the bottom view down here we can take a look at this again we're gonna have some space in between and we'll notice they're equally spaced out and basically this is just a bunch of boxes again so we just have a bunch of boxes and they just repeat each other the boxes themselves have a couple states we can see that here this has like some numbers and this has just blank but this is actually not too complex right so we're going to have some padding of some sort on this as well equal on all sides we're going to notice there is a border radius around it so we gonna have a circle and then inside of this so this is going to be a view right and then inside of the view is going to be some text the actual number itself anyway that's kind of how i like break it down the layout before i even start coding i actually like will think this all in my head and kind of just go through how i break down the ui and that's kind of what i imagine each little piece to be uh all right so now that we kind of have an idea of what each piece is let's go ahead and start making this so i said the first thing we're going to start with or at least the first thing i think about is this outside container so we're going to kind of create that so let's hop on over to our code and i'm going to make this into its own component and i'm going to create a new folder here called ui and i'm going to call this the workout card dot tsx and the reason why i made i made a folder for it is because i see this as a piece that could be used across our application it's kind of like a shared ui piece so i'm going to say rh for my react hook snippet and we're going to say workout card and so i'm going to say rnss this is my snippet for style sheets and we're going to start by having an outermost view and so this view is going to be that card that we just talked about and let me just push this over a little bit so we're going to say card and we're going to just apply that style onto this real quick so we're going to say style styles.card and then just for the sake of viewing it i'm just going to say text hey guys i'm going to import that and i'm going to import all these things so i just hit control and space to bring up the intellisense and i'll do that other other thing i wanted to mention is you don't always have to do the hotkeys too there's this little light bulb that sometimes appears you can click on that and then i'll do the same thing where you can auto import things all right so now we're going to deal with this card style so i already said the border radius we're going to have something it didn't look too bad some say like a board radius of 3. the background color was white so we're going to say fff and then lastly was that box shadow and i actually didn't even know how to do a box shadow and react before i did this so i just went on over to or sorry react native so i just went over stack overflow and saw this answer and we can use these properties uh to add a box shadow and then and all these chat uh variables we can kind of play with a little bit to get a better shadow uh i played with the numbers a little bit and i thought width of two height of two and then a shadow opacity of point three looked pretty nice but uh basically you can do whatever you want and i think i also set the shadow radius to match the shadow ray or the radius that we used up here so the other thing i like to do is just to render this right away and kind of get a feel for what it's looking like so i'm going to just go over to the current workout screen that we have and i'm going to just render a workout card workout card and just to get a feel for it the other thing i'm going to do real quick is add a style sheet here i'm just going to call this the container and i'm going to set the background color just for this page to be fa fafa that way we can just see some contrast between the actual background color of the card and the background color of this oops we're gonna say styles.container all right give that a save and let's go take a look at our content i don't know if i mentioned this but i'm gonna have just like the uh yarn watch running on the common package and then i just have my server running from the web so those are just kind of constantly running throughout the series all right so let's go over to that page by saying create workouts uh here we can see our card being rendered um the other thing i'm going to do is just add a little bit of margin everywhere so i'll say like a margin of 10. that way it's just not up against the edge and i can see it a little bit so there we go nice other thing i'm going to do real quick is just head over to our router store and set the default state to current workout so we don't have to have the screen change every single time all right so this is a good start for our card so why don't we start making uh the two uh top view first so i said there's going to be a view here and a view down here so we're going to create those two so uh back to our workout cart so here i'm going to say this is going to be like our top view and then we have a bottom view and uh here we're going to say flex direction is going to be a column that way we get them stacked and again i can display some text if i want to and just say bottom for now because we're going to fill on the top first so for this we saw some text and this was actually the workout they're doing so why don't we take that as a prop so here i'm going to say uh exercise and that's just the name of the exercise and we're just going to take that as a prop and we'll render that here uh and then on the other side we saw was i believe was just uh i guess the amount of reps that we're doing and then for the weight that we're doing it at so we could just say um here we'll say reps and weight as a string and we'll take that as another prop that we're gonna have on the right side so reps and weight um and i guess it's the set as well but uh that'll cover it so actually not i guess we it's better to be the most clear so uh one thing i can do i don't know if i hit f2 uh it brings up this little window i don't know if it's going to rename it here and here let's see if it does or maybe if i do an f2 here it'll do it so i'm going to say reps sets and weight i don't know if that really uh that really even looks that good of a variable name i think i like reps and weight better it just looks a lot cleaner all right anyway it didn't really f too well all right so let's add that so i'm going to say exercise it's going to be squat and the reps and weight is going to be a 5x5 and we're doing 260 today um the other thing is if we look at our workout card right now i believe the text probably is like all mashed up against each other nope it's actually rendered below each other that's kind of interesting i would have thought they would do you know what i think the default might be a flex direction is a column instead of row maybe i can't remember anyway so we're going to add a style to this that way they are next to each other or not next to each other at least on the same line so here i'm going to say top row and we're going to say flux direction is a row and then we're going to say justify well let's just see what that looks like for restraint before we add the next step so we're going to say styles.top row and now they should be side by side nice and so now we just want to add space so this is on the other side over here so for that we're going to say justify content space between and so now it's going to just jam space between them and they're now on the sides so i mean the next thing is we want to just add some padding and we're basically adding padding all around the cards itself so i can just say on my card up here you can just add a padding of i don't know like 10 or something see what that looks like um that looks pretty good we could maybe add a little bit less it also looks a little spacey on the bottom but we can make these little changes later the other thing i'm just capitalized squat and over here i'm now going to just maybe make the text a little bit bigger so here i'm going to say top row text and i don't know font size 16 style styles dot top row and then same style we're going to apply to the other one as well all right let's take a look at that awesome uh so let's do the bottom row now so we have this part and let's go back to our whiteboard we don't really need this anymore so the bottom row again we're gonna have a view and you'll notice it's kind of a row and then we're just going to basically be looping through um these five different things so let's actually add the prop for that first so this is going to be basically these sets and this is going to be um i guess this is really just an array and it's going to be the values either i think i'm going to say the value is a string because there's a couple different states one of the states is an x marked through it one of the states is blank and the other state is a number with a color so five four three two one and so on so i'm gonna just say this is a string array and i guess i guess this makes more sense to say reps but we already said is this really is this considered reps or is this considered set um i guess it is sets this makes more sense i think um all right so we have an array of sets and we're basically going to map through that and render them here so we're going to say sets dot map and for each set we're going to return a view so first off uh actually i'm not sure the best thing for the key itself i actually think the only key we have for this is going to be the index so key we'll say it's the index because there's really nothing unique about the set themselves it's just going to be the number five or something all right and i guess we could say set plus the index that may i guess makes the most sense all right so this view is going to be that red circle thing so we'll style that in a second because it can possibly again be three different states so why don't we say um if set is equal to x then we're going to return just the text x and we're going to style this in a second if set is blank we're going to just render a blank text otherwise we're going to render the circle right here and for all of these we're going to have to say a key so key all right the other thing is this is also going to be a row so why don't we just add the style for that real quick so this is going to be the bottom row and flex direction is going to be row and then the uh we're gonna use justify content and we're gonna say space uh we wanna do space between but we also wanna do i think i don't know if space between or space evenly is gonna work out better well i'll just have to see what it looks like all right so why don't we start with what the red circles look like and render that first so we're gonna have some kind of view with a large border radius so i'm gonna say circle is going to have a border radius of say 9 and then we're also going to have to set a background color and i thought it'd be kind of nice to instead of just copying their color scheme to make our own color scheme so i just went to color.adobe this is a nice little tool uh it has a little color wheel where you can put a color and it'll give you there's different ways you can do to create basically color palettes so right now i'm doing complimentary color palette for just white and so we're gonna make our little circles this green color all right so come back over here and we'll render this color for our circle all right so here we're going to say style styles.circle and then inside of that we're just going to render some text and we may need to like align this in the center and stuff and this is just going to be the set itself so let's go ahead and add some sets over here so let's say for now we're just going to do an array of five and we'll have that a couple times so five sets of five is what we'll do at first and let's just see what that looks like um didn't i say flex row i thought just see what i messed up with my card because they're all stacked did i do bottom row flex direction is uh a row so okay i just didn't actually set it okay so we're gonna say styles dot bottom row and let's see what that looks like now um all right uh we should we didn't actually do a very good job because we need to add i guess some padding to make it more circular so let's play with the padding a little bit i don't think i really made too many circles like this let's do like 10 just see what even padding looks like alright so this looks kind of blocky i think i just need to add like a border radius of way more maybe like 15 and then i'll get more circular all right we got an oval 20 uh is that as much as we can go so let's say padding of now 30. um that's like that all right let's say board rate is 30. um all right we're almost at a circle i don't know like 60. just get let's just get there i feel like there's probably an optimal circle amount here i'm gonna have to google this after i'm done with this video i think we'll just call this good for now and then i'll google if i just need to do i don't know if you're just supposed to set like a giant border radius to get a good circle or what because this is still looking a little weird here uh anyway so let's shrink the padding a little bit let's do like 15. um and then let's go ahead space evenly looks pretty decent i think the other thing is i want some like padding on the bottom itself i also want to make the text of this white so uh this is going to be circle text color is going to be fff so this is the circle text and then i want to add some padding to the top of this so on our bottom row i'm going to say margin top and let's just say like 10. i know 10's like the magic number today uh we could probably do like a wee bit more maybe like 14. all right um all right this kind of looks like what it should look like i think um let's go ahead and do the other two states so there are two states where there's an x in the middle and that it's grayed out all right so for us uh that's gonna be these two right here um and we're gonna use the circle in all three states that's something i didn't really think about so uh what we're gonna do let's copy this the only thing that differs is its color so we'll taste that and what we're going to do is just take an array of styles and here we're going to set i guess styles dot gray and all that styles.gray does is set the background color to gray and so this is going to render some text and it's going to be an x let's do a big capital x oops and this is just going to be a blank there's going to be nothing it's just a single view oops and let's close that tag alright so let's add the styles.gray background color and i don't know if i ca it came with a gray over here that would work um this is f oh all of them are fff this brown could work as well let's try that out um let's see if that looks funky or not i guess it's no longer really gray all right so let's let's render a few different ones so this is going to be an x all right let's let's do that one blank and this one's an x all right so these are two different states for it so this has a slightly different padding uh if it doesn't have a number or not so i think when i had to figure out how to do a nice even circle we'll fix the padding on this thing but i think that looks fine enough the circ the text itself we could probably uh increase a little bit on all of them so we'll come back to our card so i said circled text right here i think i'm going to just rename that to white text because i want to say a circle text and set the global font size by the way i did f2 to rename that that's how that little pop-up came up and i think it renamed it down here automatically for me so just a heads up on that so circle size we'll say font size of let's do 15 again or did i say 16 above we'll do 16 again and then i can set that here so style styles dot circle text and we'll do that here as well so it's going to be white text and it's going to be styles.circle and one last thing i want to do is actually make this x like more of a gray color i think i already did gray here this should really be the background could be like faded background because we could change the color on that so this is gonna be gray text and we're gonna say color and i'm just gonna say gray uh and you know i spelled it with an a there and an e there all right so let's add that styles doctor let's take a look now we kind of grayed out x that's kind of the feel i think they had on theirs so there we go that's basically the start of our kind of our component card here um i think in the next video what we'll do is we'll perfect the circle itself uh also i wanna before we end the video just see how space between and space evenly looked um so space between spread it to the edges maybe that's better i think that fit more to what this was doing whereas on the edges yeah i think that was closer to what this was like so yeah we're going to make this interactive and actually respond to for example clicks and we'll also get the circles working so we're going to start by making these ovals into circles thank you guys in the comments for suggestions on how to do that and then we're going to be making them interactive so when you actually click on them they're going to change and then lastly i got a cool mobx tip in the comments as well that we're going to implement we're going to be doing a root store that we're going to set up today so to start off let's go ahead and fix these circles so we're going to go over to our circle style and we're going to remove the padding instead of padding just doing a height and width so a height of 50 and a width of 50. and then the recommendation was to do half of the height slash width as our border radius so in this case we'll do 25. so if we come back over here you'll notice they are way more circular now the number itself is now off the plane we can fix that by coming over to the circle text and just saying margin auto give that a save and now we have it centered the other thing i want to mention real quick is this gray that we put in there is kind of hard to read so i just went into the color wheel that we used yesterday pasted the brown that we're using and uh basically just replace it with this so just picked a different complementary color um and uh seems to work better so i'm gonna just replace the gray text that we were using so paste that in and that's what it looks like and you can see it still has that kind of faded view but it's a little bit more readable all right so let's start with this root store that i was talking about we'll start with that so the idea with this is we want to be able to access multiple stores so in our mobx we have a router store and a workout store and we want to access both of them and so one way to access both of them is for example we could say use context and we could say our workout store here in our router store and just have use context twice but downside of this we could have used contacts a bunch of times so it's kind of repetitive and also we may want to use the router store inside of the workout store or be able to access the data and vice versa so that's the what we're going to set up with the root store it's going to give us access to both of those things an easy way to access all the stores and also a way for the stores to see each other so we're going to create a file in our stores called root store dot ts and i'm going to say export class root store and the idea of this is we're going to be creating a field on the root store for every single store that we have so i'm gonna say router store and we're just gonna say is a new router store and uh we need to export it export and we're no longer going to need the context which will uh the router store context because we're just going to create a single context for the root store so i'm going to remove that i'm going to remove it from the workouts door as well and export it all right so back to our route so we have a router store and then we're going to be passing in uh this which i'll explain in a second so we're gonna do a workout store here as well all right so the reason why we're passing in uh this is that way we can access the all the different stores that are on there uh to be able to get this work to work we just need to go over to our router store and accept this as a constructor so uh let me just save all these files come over to router store and here we're gonna say constructor and here we're gonna take a root store as the prop or really this is just the first parameter of the constructor i'm going to say root store i'm going to say this dot root store is equal to root store and so what we get from this well actually let's add the type up here so root store is a root store so the advantage is now we can access it by saying this dot and restore dot and we can access for example the workout data in our router store if we need to uh and we're not going to be needing it in this video but we may need in a future video i'm going to have copy this over and just paste this into the workout as well all right and we're just going to import these and then back to our root store uh we're just going to create a context from it so we're saying export cons root store context is equal to create context and a new root store so now how we actually use this center application we can go back to our router here we're going to call this root store instead say root store context and now we just say root store dot router store to access it but if we wanted to we also have access now to our workout store so now we don't have to spam a bunch of contexts we just access it through that and then we're just going to do the same thing in our workout history that's the other place we're using the router store all right and oops that should be root store dot router store then let's import those give it a save and uh we're good to go all right so let's just make sure we didn't break anything if we come back over here and we see everything nicely i mean we didn't really break it it's compiling everything's good all right so that's the uh rootstore uh method or i guess you'd say uh uh abstraction i guess so uh next up we're going to make this interactive so to make this interactive we want to start storing stuff in our workout store basically we want to store the current workout and when the user clicks we're going to decrement the amount of reps that they actually did on that workout so for example this means that they did five reps of the squat all right so we're come back over here i'm gonna make these fields observable observable um and i'm just gonna copy that and add it to each field um and let's add a space paste that in all right and we'll remove that all right so now i made each one of these observable we're going to have an extra field on here and this is going to be like the current exercises that the user is doing so i'm going to say current exercises and this is going to be an array um so i'm going to make the call this current exercise so we're going to create this type and it's going to be an array and at first the array is going to be empty so let's create an interface for this current exercise and for this we're going to have a few things so we're going to have the weight which is going to be a number we're going to have the number of reps so num reps we have the number of sets and actually we're just going to say reps i think instead of num reps i think that makes more sense and then the exercise itself which is just going to be a string um so that's pretty much all the data that we need to know about this uh so we're just going to head on over to our workout history and we're going to just create a add-on to this current exercise array so here whenever we transition screens right here we're just going to say root store dot workout store dots current exercises dot push so we're gonna add a few exercises for them to do uh right before we move to the screen so oh there's one other thing that we need to add to that we need to keep track of the sets that they're doing so sets is going to be an array of strings all right so here we're going to say uh the name or the exercise is going to be squat the number of sets is going to be five the reps is going to be five now the sets is going to be an array that looks something like this so five five five and i think later on we're going to make a function to automatically create this for us but we'll hard code it for now and the weight we're going to do at 260 today um and so if we wanted to we could do this a couple times and i think with push you can actually make this into a single call so if i just do a comma there you can do it like this and we can do another exercise so say we want to do the bench press bench press we'll do five five and then the weight i'm only going to do 200 on and then the deadlift we're only going to do one set so i'm going to say deadlift for 360 and this is all going to be x's all right and number of sets is just going to be one all right so let's go to our current workout so that is basically just going to read these values map through them and render the cards so let's do that we're going to first need to wrap this in an observable obser or sorry observer because we want to access that context so root store use context and here we're going to do the root store context and then instead of just having a single workout card like that we're going to say root store dot workout store dot current exercises dot map and so for each exercise which i guess we'll just call e we're going to return a workout card um so here i'm going to say the key is just the name of the exercise and we can say exercise there and then the this this little thing right here we can create so we'll make this a string template so this is the amount of weight that they're doing so e dot wait this is the number of reps so e dot reps and this is the number of sets so e dot num sets and then this is the sets themselves so we're going to say e dot sets so we're going to give that a save let's come look at that and it should just be rendering a couple cards but i messed up somewhere the other thing that i wanted to do real quick is uh oh we add observer here we're gonna have to add observer to the workout card as well because this is actually using the mobx values i don't think that's our particular problem though observer um the other thing i wanted to do real quick is just in our i noticed when this was blank that this was not the right color so if i come back over here and we go to our workout history um oh sorry it's current workout you notice how we set the background color to f a fafa it's not showing we just need to say flex one i believe so it stretches across the whole screen okay so now you'll notice we have like this light gray and then there's this light blue because we have some margin in our index i think um no we didn't add any margin here i don't know what we have a margin on i don't know if we set a margin anywhere in our application it could just be on the body itself that there's some kind of margin we do an inspect maybe we'll be able to see it we set a margin left oh you know what we did set a margin we set it right here let's change that to padding and there we go now we have fully grade all right so let's figure out what the heck is going wrong with this oh yeah so we're actually starting on this current workout page when really we are never coming over to workout history and adding the items to the array so that just means we need to come over to our router store and change the what the uh basically the starting route is supposed to be workout history so now if i come back over here we create a workout we can see the cards actually showing up so nice let's add a little bit of margin so that they are not just like smashed against each other but we can see we're programmatically creating our workout right here so that's pretty neat um so just go back to i guess the workout card and then in the card itself we'll just set a margin bottom of 10 that seems to be the magic number we've been using and create workout nice all right so lastly we just want to be able to click and this will be kind of cycle through so to do that we're going to just add an on press now we can't add an on press well maybe you can on press the view i don't even know if you can doesn't look like there's an on press property but anyway we're going to use touchable opacity that has an on press that we can use and then what we're going to do is take a on press function as a prop here so we're going to say on set press and what we're going to pass in is the index that they pressed and then it's just going to be returning void so this is the type definition for a function and so here we're going to say onset press and here we're going to say onset press and then we're just going to pass in the index so in our function up here we're going to have to actually handle this and actually update the uh the little circle so we're going to make this a touchable opacity and the x we do not need to make a touchable opacity so we can just ignore that so let's copy this and we're going to just paste it in here and let's just there we go and come back to our current workout now implement this onset press so this is going to be the set index and so what we're going to do is we basically know what the current value is so we say called v which is going to be the current exercise sets set index so this v is just going to be for example a string that says the value 5 because we're just getting the current set and so we're just going to check if the current set is blank because if it is uh we're gonna say new value is a string and we're gonna say the new value should be uh after you hit nothing it should be i believe five or really it should be the number of reps so we're gonna say e reps and we need to make that into a string so back ticks like that else if v is equal to zero it is now oops not returned is equal to an empty string single and then else the new value is going to be uh whatever the current value is minus one so value is currently a string so we're going to say parse int v minus one and then this needs to be a string so we're going to convert it like that and then lastly since we're using mobx we can just directly update the the value now i don't know if we can just update the value here that we're mapping through we can try that and see if that will work so i can say dot sets set index and that's equal to the new value all right so let's see if this updates when we click on anything now so go create and sure enough it does so we can just modify it there which is pretty neat okay so we can see we can cycle through that now um so click that notice click on the x doesn't do anything but so yeah so how this works is for example if i'm dead lifting i basically you know actually everything should start off at uh blank so go to workout history this should actually start out all blank not a bunch of fives it should look like that when it starts and then as i squat when i do the first squat i'll click it i did five reps then i did five reps and then here maybe i only did three reps and then here i went down to i don't know zero reps and i failed so that's kind of how you keep track of your reps as you're doing it so we're going to be building this little timer component at the bottom here today we're going to start with building out the ui and then we're going to create a mobx store that's going to increment the timer and keep the state for it now the purpose of this timer is after you complete an exercise you want to wait like five minutes or so or three minutes and then do the exercise again so this timer is going to keep track of that time for you and as you proceed it's going to tell you how much time you have left before you need to do the exercise again so let's go ahead and start off with the ui of this so the first thing is it's going to be at the very bottom and we're going to start on that now so the bottom we're gonna create a new ui component here i'm gonna call this workout timer.tsx and i'm gonna say react hook and use my snippet and then workout timer now we're going to render a view and you'll notice the view was at the very bottom of the screen so the way that we get something at the very bottom on the screen is we're going to be using absolute positioning so i'm going to say container style here and i'm going to say position absolute and then i'm going to say the bottom 0 and i'm going to say left of 0. that way it's starting very at the very left most and at the very bottom most next i'm going to give it a height of let's say 50 and a width of 100 uh then i'm going to set a background color for it and then for this i'm just going to go back to our color wheel and pick one of the colors let's go ahead and pick the green and paste that in and so i'm going to say style styles dot container and then inside of here i'm just going to say text and i'm going to say hello for now and we're just going to see if this renders a box at the very bottom of the screen so we'll import this and not view base view and we'll give this a save and then i'm going to just come over here to the current workout and render this workout timer at the bottom so give that a save then let's come back to our react application create the workout and you'll notice now we have a box at the very bottom and it says hello in it so that's kind of how we're going to position the box and we have to give it a height because we don't really have much content in this but i guess we could have done it based off of the content too but i'm just going to do a static height i think all right so the next thing is i'm not going to worry about the text in the middle i'm just going to have the timer on the left and then x on the right so this is going to be the text on the left and then this is going to be the x on the right so let's style each one of these i'm going to start with the x the x i'm going to again just pick a color from our color picker and i'll just go with this one and then the font size i'm gonna say as like 20. we'll see if that's too big and then this is going to be the actual time uh time text and this is going to be the color i'll say is white and the font size a little bit smaller maybe 18. right now i'm just calling it hello but we're going to be replacing that in a little bit so styles.time text and then style styles.x and then i want space to be between these guys again so in my container i'm going to say uh flex actually justify content space between and that should push them to the edges all right so let's take a look at it create the workout um it looks like i need to have them in a row so i'm going to say flex direction row flex direction [Music] grill that way they align and now we have them on opposite sides cool so next thing is i want to add basically some spacing some padding around it and basically center them so i'm going to say align items center and then i'm just going to add like a padding of 10 or something and we'll give that a save all right and we'll see what that looks like good and actually i don't want to add a padding because uh one other thing that we're going to add is kind of like a loading indicator at the top that's not something you can see in the screenshot but it's in the app itself is basically when the timer starts there's a little line that kind of goes across so we're going to be building that i guess we'll build that at the end when we have the state in there uh so this is basically going to be the time and then we have this little x i want the x to be quite a bit bigger i think maybe like 30 so it's easy to click on and uh i guess we want a little bit more spa uh space i guess padding on the side of that as well and i also want to make it uh touchable touchable opacity like that and then i'm going to say on press and then here we're just going to say uh a prop that we're going to take in here so on x press push and this is just going to be a function and that's the function definition so it takes no parameters and then returns void so nothing onexpress i'll pass that in there and so when we render it over here we're gonna have to use that on x press and for now i'm just gonna do nothing when the x is pressed so now it should be clickable so sweet and again let's add a little bit more i'm gonna say padding is like 30 and i'm just going to say padding on the left and the right side so that should be padding vertical or sorry horizontal because we're already centering it all right so cool so i'm pretty happy with this right now we can click on this the next thing is we want to make this interactive by interactive i mean this should be incrementing up as we kind of like a timer approach so to do this we're going to create a new store to keep track of this so i'm going to say workout timer store dot ts class workouts timer store and now what are we going to actually put inside of this right so i was looking at this one article and i liked their approach they were basically building a stopwatch with mobx and so that's going to be very similar to what we're doing so we're going to take a few cues for for how they kind of set up theirs so what they do is they have instead of for example creating the number of seconds that the timer has been running for basically you have a date the timer started off and then you do a difference between the start and the current date which we'll see in a second so we're going to create an observable here and this is going to be basically the start time um and so start time i'm going to just say is a new date but we're going to talk about that in a second what we're going to do instead and so basically what we want to do is also we want to know whether the timer is running so you create an is running variable and this is going to be false by default the other thing is i want to know the amount of seconds that i have basically passed so for example let's say we started a current date and then or sorry start a current or some time and then we want to compare the start time versus the current time and compute the difference in seconds so that's what this is going to store right here so the next thing is is we basically need to start the timer and we need to basically end the timer and then in the middle we're going to have this thing called measure which basically is going to be running every they did every 10 milliseconds i believe we're going to run it every second and basically it's gonna compute the difference but you'll see what this this will make more sense in a second and i'll link this article below if you want to check it out because it's pretty good uh so we're gonna create an action uh i we haven't really used actions in mobx before basically they're just a function that changed some of the variables or the fields in the store so we're going to do this start timer and i'm not going to worry about this check right here we don't really have that problem and no actually in our particular application we actually don't want it to function like that anyway all right so they what they use for the start time is they're using uh moment and so we're going to be using a slightly different library for that it's called day js so we're going to install that and it doesn't really matter what version you install that you're an ad so just go ahead and do that and basically djs is is a moment but it's not as large i believe it matches most of the apis if not all of them but it just does not have a giant bundle size and we don't really need all the features of moment anyway we just need the ones that djs supports really we're only using one function of it which we'll see in a second so we start the timer we're basically going to say we're currently running so we set that to true and then we get the current time and then we're just going to import djs here uh there we go and then we're going to call this timer uh and then instead of new date here we'll call new here we'll call we'll make it a day js as the default all right so let's do the uh measure action oops should be measure actually i can just copy their measure we're going to basically do that all right so their measure what they do is if it's currently so if you turn this variable off measure is going to stop because basically what it does is it recursively calls itself so as soon as we say false it's going to stop running so that's what that does what it does next is it sets the current uh difference in time so that's gonna be the seconds variable for us since we don't really care about milliseconds and then lastly it's gonna do set timeout and so what set time it does is after this many milliseconds it's going to call this function and so you notice it's calling itself so it's recursively calling itself waiting 10 milliseconds for us we just care about seconds so we'll do that and then this i'm going to call this seconds and we're going to say djs.diff and then we just have to say the unit that we want back in this case uh the second so what's going to happen is djs creates a date object and the current time so it's going to say the current time difference to when we started and that's going to be in seconds all right so we have start timer the last thing we really need is just to end the timer and to end the timer it's very simple all we do is we set is running to false and then that stops it from basically continuing to measure itself over and over again and by the way whenever measure gets called basically we're going to be able to see the new value of seconds and that's going to re-render our application so that's how that's going to work and then we basically want to just add a helper here which i'm calling display and it's similar to what they did and we're going to say computed and this is going to be display and so we haven't done a computed property either so a computed property is basically it uses some of the fields and it generates a new field based off of it so for example we're basically going to take the current difference in seconds so there might be 30 seconds difference and we're just going to format that into a string so we're going to say and also this is going to be a variable that we want to actually i'll show you guys the difference before i'm going to add the get keyword but i'll show you what the difference is with including it and not including that is so here i want to display the number of minutes so i'm going to say this dot seconds divided by 60 and then i'm just going to say math.floor on that and i guess i can say const minutes to be super clear and then the number of seconds right is going to be this dot seconds mod and then all i want to do is i may want to pad this with a zero as well but i guess why don't i show you guys what this looks like first minutes colon seconds all right and now if we go back over to our current workout i want to pass to our workout timer the current time so we're going to say current time and we're going to say this or sorry not this we just need to access our root store and we'll say root store dot and now we want to access the workout timer store so we need to add that to our root store so let's go to that and we're going to say workout timer and i'm not going to worry about passing this in because we're not going to need it so now we can access that over here and we're going to say dot display and we'll come back over here and we're going to say current time is a string and so instead of rendering hello here we're going to render current time uh and if i come back over to this you'll notice i'm calling display like a regular function now if i want this to be more of a property that's constantly changing instead of calling it as a function i can do that and that is what that git keyword does so when i say git basically it's going to call the function to get the property and now we can use it as just a regular property and we can access the field like that so pretty cool so let's just see if we see stuff and we don't get any errors oh let's re-watch now you'll notice we're not actually starting the timer so that should uh we shouldn't see it ticking but if we right here on the workout card when we press on a workout um i guess we'll do it at the bottom here now i guess let's just do at the top i keep wanting to say this but we're just going to say rootstore.timer.isrunning or sorry we don't call is running we say start timer and that's just going to call our action to kick things off all right so we'll come over here so we can see it's zeros we can see our x here and if i press this you'll notice it's incrementing every sync it now so pretty neat um so let's take this a step further one thing is we may want to pad this with a zero so it just looks a little bit nicer so i guess we go to our workout or store and we can just make a simple utility function and we're just gonna say const pad zero and this is just going to take a number and it's going to say if number is greater than 10 greater or equal to 10. we'll just return it otherwise we're going to return it with a zero in front so give that a save and then we can wrap these pad zero and now i think we should see zero zero click on this and it increments nicely cool uh the other thing is i want to close the timer when i click on the x so and that should really reset the timer as well so if we come back to the current workout and the on press here we're just going to say rootstore.workouttimer and we're going to say stop or end timer i guess that's what i called it we'll pass that in so now we'll let tick one two three or whatever click the x and oh it's not cannot add property is running object is not extensible oh what happened to this workout timer what i do this dot is running is now false i wonder if it's because i didn't call it in a lambda if i do that i wonder if it works see so start it increment do that yep and it looks like i guess i'm not resetting the seconds to zero so that would be a good thing to do but that stopped it i'm actually not sure why i need to do a lambda with this probably something to do with it being an observable or something that was causing it to be weird things so in this we're going to say this.seconds is equal to zero too uh the other thing is we only want this timer to display if it's running so we're going to say this dot sorry root store dot workouts timer dot is running and if it is and we can just do a ternary otherwise we're gonna terminal reason why i went with ternary instead of doing double and there is sometimes i've had problems with that with react native doing the and so i usually do that so we should not see the timer right away i click on this we now see the timer and it started and it's going uh the last thing that we can do is we can add a little progress bar if you wanted at the top here that kind of goes as it increments but before we do that let me click the clear make sure that works click it again nice also if i click this i want to restart the timer nice that worked the other thing i wanted to do real quick before we actually do the progress bar is i want to stop the timer if this component gets unmounted so to do that i'm going to say use effect and i only want this to run once and in the cleanup function here all i'm going to say is rootstore.stop timer or into timer and i'm just going to go to my thing real quick and rename this so i'm going to push f2 to stop timer because i constantly keep typing that um and that should rename it over here and f2 did rename it over here for me automatically cool uh so so with the use effect you'll notice i returned a function this is the cleanup function meaning it's only going to be called this component i believe is getting unmounted so it should stop the timer then and then i put a brackets here because i only want this to be called at the beginning okay so let's do that progress bar real quick that should be pretty easy if we go to our workout timer basically all we're gonna do here is we want to have something that has a width that changes so here i'm gonna say line it's going to have a height of let's say three uh we're not going to set the width background color of this again let's go pick up color from this uh let's try this brown see how that looks and let me think if there's anything else i don't think that's anything else that needs to go with that i want to wrap these guys in a view and then i want to have a view up here and this view up here is going to be the line and it's going to sit out on top so styles.line so basically at the very top of the component i want the line and then i want this stuff inside of it but i kind of have some flex stuff going on so i'm going to have to move that down so i'm going to create a style called row and what row is going to do is it's going to say justify content flex direction and center all that fun stuff all right so we'll put that here style styles dot row all right i'm just gonna see what this looks like um and this is going to be a array because we want to pass in an a width and the width is going to be constantly changing so i'm just going to set the 50 right now so we can see what it looks like press this all right so i can kind of see this thing right here you'll notice how it's getting pushed to the side because we have some padding so what i want to do i'm going to say with this view i'm going to have it flex so the row here is going to flex one and i'm going to move the padding to the bottom to the row all right and press this and now it's right here now that's super hard to read so why don't i pick a different color uh let's try this one and see if that shows up better if it doesn't we can just pick white too all right all right that looks way better cool and so what's going to happen is we basically just want to compute the percent of the width we should be showing and we're going to just take that as a property and compute that in our store so percent is a string percent and that's what we're just going to pass in here all right so we don't really have a percent yet so we're going to create that in our store so i'm going to say rootstore.workouttimer dot percent and then let's go create that percent so our timer over here this is going to be another computed property and i'm going to say percent and basically what the percent is going to be is i don't want this to be any bigger than a hundred percent so i'm going to say math dot the smallest number here the max or the max it can be is i want it to be no bigger than 100 and what's going to happen is i'm going to put a percent sign here at the end because this is just the format of the width and then here i want to get the current diff so that's going to be seconds divided by whatever i want the completion to be so if i want the timer to run out at 3 minutes i'd put 180 seconds if i wanted like five minutes i would put what five times sixty three hundred all right so if we take a look at that we should be able to see a little timer that will increment i don't see anything so i wonder if i messed something up i'm just go over to the percent and console.log it and see what the value is so console.log be percent and see what we're getting because basically what we want to display is uh a zero percent good and then it should be incrementally getting bigger okay so it's super small right now so that's the problem so i just need to times this times 100. so wrap that in parentheses and to say times 100 give that a save click that and there we go so as we can see it's kind of ticking and we can see the percentage is increasing there we can see we have like a little progress bar going now so that's pretty neat and then so basically all right i want to do one exercise it's gonna reset the timer and then it's gonna go and let's say i'm done waiting i can either just click the x or i can do that and the other thing is when it gets down to zero and i click it and it goes here it should clear the timer as well so let's add that real quick that's very easy too that's going to be just uh so when it's zero and we click to make it nothing we're gonna say rootstore.workouttimer.stop so we could stop the timer by clicking it a couple times and going to zero and clicking it sweet so anyway this is pretty nifty uh i'm really enjoying mob x and i really like just putting these values um into mobx being able to create these computed values automatically that are automatically changing as everything is changing and then we can kind of uh we basically just created this measure method that just constantly tapping every second that is causing a re-render and changing the time on the screen and the other cool thing about us using start time is if for example we were to persist the state which we're going to do later and the user comes back they're going to see how much elapsed time has happened because we're storing the start time so we are revisiting the topic of navigation today because we have a little bit of a flaw in our current setup so right now we are storing the navigation state in mobx and what that means is we're not syncing it with the url right now so if i were to create a workout this is a different screen and you'll notice the url does not change and that is the flaw that we currently have and so what that means is if i were to refresh the page or just revisit this url we'd start back over here and there's no way to visit this screen directly which you would experience with a regular website oops so that is what we're going to try fixing today now you'll notice the reason why i picked this option in the first place is because i tried out react navigation and the web version of it was not very good and it would be very difficult to try to do get that to work and also get it to work with the native version but i forgot about this one package that i used to use for a react native called react router so react router is the standard for the web navigation if you're building a website and react you're probably using react router but they also have a native version and i use using this for a little bit but i found react navigation to be way stronger when using yak native but i think react router is a great choice for what we're currently doing because it is a very similar api between the web and the native so if we just look at what the web looks like we can go to the quick start you'll notice basically what they do is you create a router and then you put routes in it and the native version is the exact same so if we come look at this we go to the quick start we're just going to create a router now they call it native router so we have to deal with that but you just say routes the same way and you deal with api in almost the same manner and it's not widely different so this is going to work great for our react native web because we can easily switch between the react native and the web version so that's we're going to implement today so we're going to start by coming over to our code and i have the router.tsx open in our common package because that's what we're going to be playing around with so to start off i'm going to just install the types for both of these packages and then also the packages themselves and i'm installing that version 4.31 and 4.24 and you'll notice i'm installing react router dom and react router native and then when this is done we're going to install the packages themselves react router dom and 4.3.1 at dom and the native is 4.3.0 all right so the next thing that we're going to do is i'm going to just rename this current file that we have router to routes just so it's a little bit clearer so i'm going to rename this to routes and it's gonna ask me if i want to update this everywhere i'm gonna say yes so what that means is in my index file where we're importing the routes it just automatically renamed it for me all right i'm also gonna push f2 and rename this to routes so save that and save that over here again just refactors it in vs code so it's now updated over here so now i'm going to create a new folder here and i'm going to call it router so that was the whole reason why i just renamed it because i want to create a new folder called reader here and then i'm going to create a folder called index.ts and or sorry a file and a file called index.web.ts so this is how we're going to get things to work so react or create react app out of the box reads dot web files first before it reads dot ts files so what that means is we can put all our web related code inside of these files and this we can call our native file code and so create react app is going to read this file whereas react native is going to read this file so we can switch them so what that means is here i can say export from react router dom and here i'm going to say browser router as router so this is me just exporting this import and renaming it at the same time we're also going to be using the route and the switch component so basically any component that we want to use from react router dom or react router native we want to export here and import them from here so you'll notice this is the dom package so this is the web version we're going to come over to our index.ts file over here and we're going to say browser router we're going to replace this to react router native and then replace that to the native router you'll notice i named it router here and router here so it's the exact same name i want all the exports to match up so you'll notice we're exporting three things router route and switch and they're matching the only difference is this is coming from the native package and this dot web file is coming from the dom package so now what we're going to do is in our routes folder over here or sorry routes file over here is we're just going to import from the router so i'm going to say get rid of all this code that we have here we don't need this observer thing anymore i'm going to say router and you'll notice i'm importing this from dot slash router now it automatically did index.web but we're just going to say router like that because we want it to just get the index file here and basically react create react app is going to pick the dot web version for us so we don't even have to worry about this all right so inside a router we're going to say route or sorry we're going to say switch first and we're gonna wrap it and switch again we wanna make sure we're importing from this package and then we're gonna have a route in there all right so we're gonna say exact path is going to be the slash this is the index or the first component that we want rendered we're going to say component and here we're going to pass in the workout history and then we can create another route which we can say current workout and this is going to be at the path slash current workout and then we're going to import route and that's coming from the router package as well and so now we can go into our uh component the workouts no not that we don't need the stores it's going to be our modules workout history so here we are connecting to the root store and we are saying changing the page here so instead of doing the router store we're going to remove that line of code we are going to be using the history and we can get the history from our props and uh we need to add the type definition to our props to let typescript know that we are a route so we're going to say route component props and we're fine to import that from react router um and so now if we go like this and i hit control space it's gonna know we have a history prop in there so then i come down here and i say history.push and then we're gonna go to the slash current workout screen so i'll give that a save so we can even delete our router store just to make sure we're not using it anywhere um and go to my root store just get rid of it there we go so again what we did here is uh because we have it as a route over here right we're passing this workout history component that means it's going to pass down a prop to it called history so this is a react router thing and history allows us to change pages so we change pages by pushing and again we just did add this to our props which are passing in here that way it just makes it uh so it's type definitions for it and then lastly just to recap the router thing that we did right here so when we do create react app or we read this in the browser so we can see it rendering right here it is using the router package to react this one this import react router dom and when it's using the one over here is when we run the app so i'm going to say yarn watch and now we can see this in action all right um we'll refresh um let's see if it looks like we got a little bit of an error i'm just going to refresh let's see looks like uncaught exception looks like it had trouble loading it i think what i need to do is in my routes i think because i didn't say slash index maybe i'm that could be causing it some trouble yeah it looks like that was it uh so it looks like we need to explicitly say slash index on there just to be clear um and now we can see it's that and when i click on this you'll notice we are going to navigate the url now you'll notice that changed and we're on this page and we can see this page here now i notice we get this little thing in our invalid prop component expected the type function but got an object i'm assuming it's talking about our workout history here we're passing we're wrapping it with an observer um and then we're passing that to the route so it doesn't look like it caused any like problem i guess just a warning not sure what's going on there i don't know if it's just a it looks like it's a prop type warning i think we can safely ignore this i don't know if there's a way to suppress this warning or anything but doesn't look like it's causing a problem anyway this should work all the same now the only difference is we now if i were to refresh the page we're going to stay on this page now we didn't really code this expecting we could go to this page so you don't see any workout data but we can fix that in the future so but now we can navigate to different pages like this and it works like a website you would expect so we can use react router to easily switch because the apis are so similar between the native and the other ones so i think this is a good choice when using react native web is to use this because you can easily switch between the two also one thing i wanted to mention real quick before i end the video is create react app worked out of the box but if you go to the docs for react native web and i'll link this below they show you a webpack configuration so you can get this working so what you basically add to your webpack say that you want to accept the extension extension.web.js or our case.web.ts for typescript and then it'll read it these type of files so we're going to be going over how you can persist your mobx stores and the reason why we want to do that is so we can keep track of the workouts a user has done so for example when i create a workout right now and i refresh the page it just disappears so i want to keep that data and keep the data as we store it in the history so if you do several workouts we have all that data so when you come back to the website we have that and so the way we're going to be persisting this is on the website local storage and on the app async storage now there's a nice library that is going to help us out called mobx persist that we're going to be using and the cool thing about this library is we can actually just pass in async storage to it and it works out of the box with react native and the cool thing about react native web is it actually handles async storage they re-implemented and so underneath the hood they're going to use local storage and persist it like that on the web so we don't actually have to do anything to get this to work with both the website and the app we just use async storage here so we're going to start off by installing this package so i'm going to say you are an ad mobx persist and i'm installing it at this version and the cool thing about this package as well is it's written in typescript so we're going to get type safe type safety out of it without having to install extra types and i'm just going to run yarn watch on this alright so how it works is we are going to basically decorate the fields that we want to persist so i currently have the workout timer store up so here i'm going to say persist and i'm gonna just import that doesn't look like it's auto completing so we'll just write it ourselves so mob x persist and so i'm gonna just decorate the persist on all three of these fields and then after we persist this what we need to do if we come look at the example here is we then have to create a hydrate function and then we just call hydrate on our store so i'm going to copy hydrate and you'll notice what we do is we create an instance of our store and then we hydrate it so i'm going to copy this hydrate and where we're creating an instance of the workout timer store is in the root so we're gonna head over here so i'm paste in hydrate here and i'm just gonna get rid of the comments and tells us if we're using async storage we need to set this to true so we'll set that to true and we're going to pass an async storage in here and we're going to import create this is coming from mobx persist so we've created this hydrate function and then i'm just going to in the constructor of the root store call hydrate and then we're gonna pass in the key for how it's gonna store it so i'm gonna call it workout timer and then we're gonna pass in the store itself so this dot workout timer and so we want to do the same thing for our workout store as well so we can come over here and i want to persist all these fields so we're going to say at persist and i'm going to copy that and i'm gonna do it for each one and that and that cool so if i go back to my root store now i can come back over here and we're going to give it another key this i'm going to call out call just work out and this is going to be this dot workout store so basically what is happening here is in our constructor when we create a new root store it's going to hydrate both the workout time restore and the workout store and what hydrate is doing is it's checking whether this is stored in local storage or async storage in our case and if it is it's going to hydrate it or put the field values into these two stores and it's also going to listen and it's going to save these values as they change over time and if we want to we can pass in i believe a debounce value to this and you can see that right there and the bounce specifies how many milliseconds we want it to wait so for example if we want it to save on every update that's the default if we want to save every 10 milliseconds or so we can debounce it that and so we could add that if we want to i'm just going to leave it off for simplicity's sake next thing is if we see if this works you can come back over here i think we should get an error out of the box so if i come to my console over here and you'll notice we have an uncaught exception it says this value is not a primitive so what that means is any of our fields that are not just a simple like number value or a string or something we need to actually specify what the data type is so what we can do is we can pass a parameter in here and we need to specify what kind of object this is or if it's a list map or an object this is a list the history is also a list and then the other one is in our workout timer store this djs is an object so we're going to say object there give that a save let this refresh and you'll notice we don't get any more error there so if now i create a workout we can see that's here and now if i were to refresh it's going to save the values in local storage and read them so now you can see that and also as i make changes so if i click on that click on this here a couple times i refresh you'll notice our data is saved so as we're working out if we were to come back to the website we'd have all that data saved now one thing you may notice is the timer right here hasn't actually started again so what we can do is we can head back over to our root store and we can trigger the timer to start so hydrate actually returns a promise so we can wait for the promise to finish at least i mean it's not showing a promise in the type definition here but in their example i believe they were doing dot then on it so uh we're gonna do dot then on it too so on the workout timer i can say after it's done hydrating i can say this dot workout timer store and i'm going to just do an if statement so if it's running we're just going to kick it off by saying measure give that a save so now when it's first started if it should be running then we just kick it off and the cool thing about how we started this is we're saving the date it started so if i were to refresh the page it's not like the timer is going to reset because we're saving the date it was off by or start it at and again we can click to reset it if we want to and start a new set um like that so that's pretty nifty and the last thing i want to do is just show you guys where this is actually being stored so if you go to the application tab and you click on local storage here and you click on log host 3000 we can see here is our state so you'll notice the key that we passed in here that is actually the key for local storage and you'll notice here the values all being stored and we can see all the data being stored here and it's also one of those things if you wanted to clear out this i could clear it out refresh the page and you'll notice it wrote it right away so it wrote it pretty quick if i refresh it'll get rid of that so that's how the data is being persisted and again we're using async storage so this will work on both react native and react native web because react native web implements this so we're going to be building out this component right here today so this is like a little card that tracks your history of workouts so every time you complete a workout it's going to show up on the home page as a little card like this now before we actually create the card we're going to just add a quick thing to the current workout page we're going to create a little button right here that we're can click on and when we click on it it's basically going to save the current workout to the history and then we're basically just going to render that history as cards so that's the game plan for today so let's go ahead and start with that button that i mentioned so we're gonna pop on over to the current workout screen and we're just gonna add a button and now i'm just gonna add a button at the very bottom here so uh it's gonna it can go between the workout timer and everything else and it's going to be a react native button and we can set the title um i'm just going to call say save here and i'm going to just say all caps for it and looks like i just need to add on press and the error will go away cool so we'll talk about what we're actually going to put in the on press in a second let's just see if the button shows up awesome it does so next in this on press what we're going to do is we first want to basically put the current work out if we look at our workout store we have an array of current exercises and so basically we want to store that in the workout history over here and given a particular day if we remember what this workout history is we can look up here what we did this is going to be a key which is going to be the day and then the exercises that they did that day and this value someone recommended switching it so we have format with the year up front so i'm going to go ahead and do that as well so the workout history is basically equivalent to a current exercise which has these properties so we can go ahead and just say an array of current exercises is going to be the workout history so i'm going to just move this down here and so here i'm going to say current workout or current exercise an array so basically on a given day someone did an array of current exercises is the idea so we don't really need this anymore this is comments not really representative of what we're doing so basically we're going to do is we're going to take this array and save it in the history at a current day so that means we're gonna say rootstore dot workout and then here we're gonna say history and then here we're going to actually we're not going to do it like that we're going to say dot or i guess in our case a string and so this is where we're going to actually say like a date like that and then what we're going to set equal to is the array of exercises so dot rootstore.workoutstore.his or sorry dot current uh current exercises there we are and then basically this array here we're just going to clear so then we're gonna set that to an empty array and then after that we're going to go to a different page and again i'm hard coding the date here but we're going to deal with that in a second um and this we're just going to go back to the home page after you save the workout so i'm going to say history.push push and we're gonna go to dot slash or just the slash which is the home page in history we're gonna get from the props here so uh let's add the prop type here where uh the typescript type so we're going to say route component props and then here we have access to that now so let's see this in action so if i save this it looks like either something crashed or did not push to the state cannot set the property that of undefined i hope that would make sense so if we go back to our route store or workout store we just actually never define this so i'm going to set the default value to an empty object like that all right um oh yes so this is no longer a list this is an object all right and cool no more complaints hit save takes us back to this page awesome so now if i were to go to that current workout screen directly should be blank because we cleared out that array awesome uh um so i just hit back and then this is blank that was weird okay it's loading still now anyway so the next thing is to actually format what the current day is so we're going to be using djs since we're already using that in this project and they have a dot format function that we're going to use and then we can format into the specific date we want so what we're going to do is we're going to say your year year then the month and then the day and the day is going to be padded with a zero too so here go back to our store or current workout screen and at the bottom here instead of hard coding the date we're gonna get the current day here and then we're gonna say dot format and uh looks like that auto imported for me for some reason it says require here though so i'm just going to change that to from there we are all right so we're going to say year year year and here we're going to say month month then day day so give that a save and then if i open up my application i can see what the state of everything is so here's the exercises that i did on this date and i can create a workout click on some days or some exercises and hit save so this is kind of odd it was kind of like floating there but when i move this it's anchored at the bottom now interesting so notice how this when we scroll deeper in the page this is always there i think uh i might need to like change this to some kind of like anchoring it to the bottom always i'm not sure exactly what css or style we're gonna have to apply to it to get that to fix so we'll fix that in a future video anyway let's give this a save and now if we go to our application state we should see a new day which is today's current date for me and we can see the exercises so awesome so next up is now that we're actually saving stuff in the history we want to display them here in card form so first off you'll notice that the card over there is kind of resembling the card here so i figured we would abstract kind of the logic that we used well not really logic but the style that we used for the card here into its own component so we can reuse that so i'm going to create a new file here which i'm just going to call card and this is going to say a react hook though we're not really going to use any hooks in this particular component and here we don't really need any particular props at least right now so i'm just going to leave them blank and we're just going to render a view and we're going to render the children so the children is a default prop that when we say react.fc that it automatically adds for us uh this and the reason why we are putting the children here is whenever we do card like that and then say we have text like that this is the children so we're just making sure to actually render the children so this view we're going to steal the styles that we used over here so i'm going to use my template for that rnss paste in the card and then here i'm going to say style is equal to styles.card and now let's see if there's anything here that's very specific to what we were doing i would say like the margin bottom here is kind of specific to it and also uh i guess the padding was sufficient but the margin bottom is kind of specific to that particular component so i'm going to remove the margin bottom here and i'm going to come back to the workout card and we're going to remove it here and instead we might just say like container or i guess like card container and that's going to have the margin bottom on it so now here i can render this card and you'll notice without the margin i believe the cards will stick together i think yep they'll stick together so we can just wrap them with a card container and that'll add the margin so a view and then we're gonna say styles.card container nice all right so now we're gonna come back over here and we're gonna use that card component to display over here so uh we're gonna say history car dot tsx and this is going to use that card that we just created so we're going to say card here and then what do we want inside of our card right so if we look at the thing over here we're basically taking the day that this workout happened and then the current exercises that occurred there so what i'm going to do here is i'm going to say the day which i'm going to just take as a string so if they want to pass something else like for example on going in they can and then here we're going to take the current exercises and we're going to say current exercise and looks like we didn't export it so i'm just going to go to our workout store and export this type and current exercise and that's going to be an array so we're going to have our day and our current exercises oh you know what did i misspell yep let me spell it here uh x exercises uh yep that looks good actually x er size is with an s there we go i think that's right spelling's pretty hard though all right so inside of our card here we're going to render those oops there we are so we're gonna have text at the very top and again we're just going to render the day here uh so we're gonna do any kind of formatting on that on the particular and we could even just say like header is more a generic of what we're really rendering here they can pass whatever they want in and then at the bottom here well let's actually first just import all this stuff import that import our card and then we're basically gonna loop through the current exercises that the user did that day uh and basically give a prefix of that so squat is sq bench press is bp and so i guess there's like a mapping of shorthand here so like the exercise shorthand and maybe we should put this in our store is this type i'm not sure the best place to create this map but we can say exercise short name so here we can say squat is sq and if we take a look at our workout store i forget what i was naming them i think maybe in the workout history all right so i did a capital s is that so we're going to say squat here and this should really be a capital right there all right and let's see i guess i can just write them out because i remember them so we have deadlift that's going to be dl we're gonna have bench press bp overhead press and let's just make sure i name this what i think i named it well you know we haven't even no i did capital p on that as well so let's make sure i match that and i didn't actually and maybe i should store this overhead press maybe i should store these values in some kind of enum or something uh that way i'm using the exact same name everywhere or put them in a constant variables i mean that would be better i just should be ohp uh and then the last one is row row purpose being that i just did this is just so we can have the little short acronyms for what we're going to display here so let's map through the current exercises and then for each exercise we're going to render some text and uh the key for this since we're mapping i don't think there's really anything unique about a particular exercise i guess maybe the name we know is gonna be unique uh because what i was thinking is maybe you could have the same name multiple times but uh why don't we use that for the key i think it's pretty safe so here we save exercise so inside of here the string that they were using was first the name so we're going to use our exercise short name map and then we're going to pass in the exercise itself and i'm guessing it's going to get mad at us because it's not one of these keys so i'm just going to say as any or you know what i think it actually wants us to say kiev and type of exercise short name there we go so basically the reason why i had to do this particular notation so this is a typescript thing so basically we created a map right here which it maps to squat maps here deadlift maps here bench maps here right and so if i hover over the type you'll notice it says these are the only keys available so i have to say i can't just pass a string as the key i have to pass a key of one of these things so the way i can do that is i can say type of this and then the key the key of means to grab one of these now the other thing i could do is instead i could say this is an object which the key is a string and it maps to a string and then i wouldn't have to do that so either one would work but notice i'm going to lose the auto completion so if i were to say like exercise short name dot i can't do dot squat it's not going to know that that exists because i kind of remove that i'm going to go with this approach because it types it the best or it's the strictest so okay so i put a space and then here is basically how much whether they how many sets they did and how many reps they did so here we're going to say there's an x in the middle and we're going to say c dot sets by a number of reps and this should be numb sets and i don't think i did numb wraps i just did reps and lastly the weight that they did at all right um i'll just see what this looks like now and to get a gist of what's going on and then we might need to style some of these things and i think everything should be a single line so i think this looks okay so uh we'll go to our index i guess i guess our index is really work out history page and i'm not going to worry about what we have here i'm going to just put the button underneath we're going to deal with the button in a different video so here i'm going to say rootstore.history.map so for each workout oh you know what we can't map over the history because the history is a object so i'm going to say object.entries so what object.entries does is it turns an object into an array and this array has two values or not two values but the array what it is is uh each entry or each uh or i guess item in the array is an array of itself and we can destructure it and the first is going to be the key and the second is going to be the value so value makes sense the key in this case is going to be the date maybe we'll just say dt there so here i'm going to say return and then here i can say with the workout history as we're looping through we're going to just render a history card for each one the key is going to be the day so we can pass in dt there and then here we can pass in uh the i guess what else we need to pass in we need to pass we passed the props of uh oh we just didn't import it maybe no we have the props passed in it wasn't giving me auto completion so i always just want to double check and make sure i didn't mess something up that's usually like a cue that i did mess something up all right so header now the header is kind of interesting because basically we need to take this date and reformat into something prettier but i'm just going to display the date right now uh because the date here is just going to be a string and that's fine for now and then we can make it prettier in a second and then the current exercises is going to be the value oops go this way um all right so here's our cards so we'll notice the card they're taking the entire screen with so i want to first i guess split them so there are two columns so i'm thinking a for each loop in this case maybe easier to create those rows instead of a mapping so we're going to give that a try so what i'm going to do is i'm going to create an array here called const rows and that's going to be an array and really what this is an array of is jsx elements and i guess it's an array of arrays so we'll do it like that and then we're going to say copy this dot 4 each um and then same thing here this is still we still do in this manner where the first value is the date second value is the value i'm going to say rows.push and i think what we're going to do is basically on even elements so we need the index we're going to push on to the array or create a new ray and on odd elements we're going to push on there may be a simpler way to do this but we're going to say if the current index mod 2 is equal to 0 we know it's even and we're basically just going to say row stop push and then here we're going to push on our item which in this case is a history card all right and otherwise if it's an odd element all we're going to do is get the last item in the rows and append to it so we're going to say else rows rows dot length minus one dot push and we're gonna push on to that and we're still gonna create a history so notice we're gonna do this twice so i'm gonna just say instead of doing it twice i can say const history card and do that so basically what we're doing is at the end we're going to have an array that looks something like this so we're going to have a history card and another history card and we're just going to have pairs of two like that because basically whenever we hit an even we're going to push on a new array and whenever it's odd we're going to fill the array like that all right let's go ahead and now render our rows so come down here i'm going to say rows.map and for each row we basically are going to render a view and then just put the other stuff inside of it like that and the key here is going to be the index so now we definitely need to create a style for this so we're going to say rnss row and i guess the first row is going to be a flex direction or first style i mean it's a flex direction row alright so style styles dot row give that a save see what that looks like and now we're getting much more of a row shaped at least we only have two so let's save a couple more you know what we're gonna be saving this and it's just gonna be saving over the item yeah see how we're just saving more items onto this i guess do this again interesting i guess maybe i just had multiple items on it that's why i did that um i think the best way to do this because i basically just want to fill this with some more items so i basically kind of just want like a random date is the idea so let's see if i go to my workouts history is that where we're creating it no we're current workout so basically i just need a a random date i don't even know the best way to generate that so i just looked up how we actually create random dates and i found this nice stack overflow and i'm basically just going to copy and paste this and just see if this works for the purposes of just generating some fake data for us so i'm just going to paste that right inside of the djs function and uh let's start creating some fake dates awesome so it looks like it does in fact work and this is just some fake data for us so we can see some days being rendered there's two big things that we're going to be doing in this video the first big thing is fixing this row or this grid right here so it's not all mashed up together and then secondly we're going to make these clickable and when we click on them we're going to be taken to a new page where we can actually see the workout data for that day and so to do that we're going to be creating a new route which takes some route params using react router but before we do either of those things there's a small fix we need and that is with the create workout screen so you'll notice it is a long list of stuff and if i click here to start the timer and start scrolling this thing just randomly starts floating in the middle here so we're gonna fix that real quick so if i come over to my current workout what we're going to do is we're just going to wrap our button or everything in a scroll view besides the timer so i'm going to say scroll view and wrap it all the way here and so this is a react native element that just makes things scrollable and we'll immediately notice we have a scroll bar here now and as we scroll uh this is visible still but you'll notice it's blocking the button at the bottom if we click on that so we may want to add like just a little space at the bottom so it fits so i guess uh if we go to content uh inset is that uh uh um that might be the right thing but i was just planning on doing content container style and then setting it like a margin bottom and like i don't remember how how big we made it like 50 or something um so that way it's pushed up a little bit and you can still see that there so sweet third thing is you'll notice like there's a little bit of spacing right here because the scroll bar is we have some padding on the view and not in the scroll bar so what i can do is say scroll view i guess scroll container is a better name for it and we're going to just move the padding to the scroll container i'm also going to take the margin bottom and put that in here as well and pass that to the content style and that should have an r there and you'll notice i'm using the content container style on the scroll view as opposed to the style this is something to actually access the content or the view that is inside of the scroll view so that is on purpose and so we only have the scroll bar there cool so all right let's jump into the main thing we're going to do today so the first thing was at this home page over here fixing up the grid that we made so someone mentioned possibly doing like css grid here and i think this is like an excellent use case for css grid but unfortunately react native does not have css grid all they have is flexbox so that's our only thing now there are some grid libraries but basically they just wrap using flexbox so we're gonna have to deal with this ourselves all right so with that said the first thing that i want to do is just wrap our in workout history wrap our cards in a view and what i'm going to say here is i need to move the key since this is the outermost view and we're going to create a new style for it so styles dot i guess we'll call this card container and so what's going to be inside this card container is i'm gonna say first off a flex of one so what that's gonna do is it's gonna have it expand across the whole half so flex one on this one flex one on this one it's gonna split 50 50. next thing i'm just going to add some padding say paddington that way they're a little spaced out and we can actually start seeing some cards forming so nice so this looks a little bit better and then maybe we want to do something besides two because these are not that wide of cards so we can go to our i percent two and we can increment this how many columns that we want so in this case let's do three columns and we have three of these now notice that because we're using flexbox these are flexing all the remaining space so here this is doing a 1550 split here uh so what we really need to do is kind of add some placeholders in this case i think is the easiest way to solve this so the way i'll usually do this is if we go to where we're rendering this row i'm just going to check the length of the row so if the length is less than three items then we know we need to have an extra view otherwise we can just render null and so this view is just going to be a placeholder so we're going to create a styles.placeholder and we'll come back to our style up here and first thing we're going to do is just say flex 1 on it and you'll notice uh that's going to have it there and you know what we're going to apply the same things as the card container so instead of using placeholder we can just reuse that style but anyway you'll notice that we'll uh at least push it over a little bit and now to match the padding we're going to have to use the same thing as cart container and set a padding of 10 on it but since it's a duplicate i'm not going to do it i'm just going to say styles.card container and reuse that style and now you'll notice we have basically there's an invisible placeholder right here that you can't see if we set like a background color you'd be able to see it's like background color pink right um you'd be able to see there's one right here and let's use margin instead of padding and it'll be even clearer all right and you can see here is our little pink placeholder there anyway let me put that back all right so this is the gist of this uh i also thought we could have a ton of workouts uh in the history so i figured it'd be a good place to use a flat list that's a component in react native that is good for lists that are long so we're gonna have to re-kind of think about how we have this current set up a little bit because we can't in this particular format render the flat list well so what i'm thinking is to reorganize this a tad instead of like putting making a rose of jsx we're going to create a new slightly new data type here so i'm going to comment this out and so what i'm going to do instead is our rows are going to be still a 2d array but i'm now going to create a new data type here inside of it i'm just going to say the date which is going to be a string and then i'm going to say exercises which is just the array of current exercises so this is kind of a similar data structure to what we had before a 2d array but now instead of having uh gsx we're going to be rendering just we're not rendering but we're going to store objects the objects have a date which maps to this and a value which maps to these exercises so to match it the names i'm just going to say date and exercises here um exercises there we go i have trouble spelling that word and then we're going to put this here date exercises and same thing goes here and the reason why we're reformatting it like this is this is just a little bit easier of a data structure to pass into a flat list all right so we'll come down here and i'm going to say flat list so first thing that i'm going to do on this is pass in the data which i'm going to have rows and two things just hit me that i forgot to do one we may have to have two placeholders if the length is if the length is only one then we're gonna have to render two placeholders so we can do it like this so if the length is two this will be false and will only render one placeholder but if we have uh one both of these are going to be true and it's going to render both the other thing is i brought a tab up for it because i want to show you guys on the scroll view that we made we need to set this keyboard should persist taps what this does is sometimes in scroll lists you have trouble tapping on things and we want to tap on uh the items in that scroll list so we can get around that problem by passing in always and i'll link the docs if you want to see the other options you can pass to this and this allows you to tap and it not and have it work correctly but anyway back with the flat list we're passing in our rows and with a flat list let's import this and uh if you didn't see that flawless coming from react native itself so there is a prop on here called key extractor so what k extractor does is it takes one of the items so in this case i'm just going to say item and if we look at what the item is we can hover over it and see you'll notice this is an array of dates slash exercises and we need to return a string that is a unique key so i think what i want to use for the unique key is the dates and i want something like if i have three dates i think i want to have something like this so date one and then like a space date two and date three all in a string so we have an array so i think a good way to take that array and turn it into string is to use the reduce function so we can say item.reduce so this is an array function the first parameter is a function that takes the previous value and the current value and then we have to return something and then the second value of this is our initial state which in this case is an empty string so how the reduce function works is it's going to call the function that you pass in for each item and each item it's going to pass in for the current value and then previous value is going to be either the initial value or whatever was returned before so what that means is we're going to say previous value plus put a space between it the current value so all that's going to do is it's going to make a string that looks like this and it's going to append the three dates together and then lastly we need to render the item for this and this is really what the row is going to look like so we can copy what we have here up here and then this is going to be item is the key to access and you'll see same thing as we were dealing with before now we don't have to actually pass a key to this because that's what key extractor does all right so we're going to keep this and all we're going to do here is kind of a mix of what this and what we did up here so i'm going to uncomment this and bring it down here so to render this all we did was loop through the exercises so here i'm going to say item.map and for each one we're going to render this and so here i can say date and exercises so the key is going to be a date the header is going to be a date as well and this is going to be exercises and we just need to import that so we don't need this we're going to need this these two placeholder things here still because this is gonna we're still gonna need placeholders because we have odd numbers out or whatever all right so item and item give that a save um so i don't think we'll see anything different here and let's see did i mess something up pretty badly i think um this looks good here we don't need this anymore i think that could have been what's causing yeah if that looked like it was causing the problem uh and this is the same two children with the same key object object object that's because i didn't say current value dot date okay so current value is if we hover over it we can even see is the object it's the date which is string and the exercises we have access to so we want to use the date to pin that and then previous value again is whatever we have on there and you can hover over it you'll know it's just a string it's going to be this and then it's going to be whatever we turn return before it as it kind of maps over each item all right so you'll notice it looks the exact same but it is now in a flat list meaning it will work better with long lists of data so last thing that i want to do is make these clickable so and basically take you to a new screen when you click on it and i'm just going to get rid of this comment because it's not relevant anymore get rid of this as well okay so to make these clickable we can go over to our card and we're going to take an optional prop called on press and we use the question mark to say it's question uh possibly undefined and here we're gonna say onpress so if they pass in a on press we're going to use a touchable opacity instead of a regular view that way it has a nice on click and we can still use the same styles.card so it's going to look like a card but now it's clickable all right so now in our workout history over here i can pass an on press to this guy right here or actually i guess because our history card underneath uses yeah uses a card right here so i guess it would work like that so i guess i can just use the the header which is a date i'm just thinking my head i guess we want to pass the on press here i think we want to add an on press here though i was thinking whether we want to put the logic and the history card or move it up and i think i want to move it up to put it here instead of past you putting the logic of how the changing of page works so in that case we're going to pass a prop down called on press and we're going to pass that in here so now in our workout history we're going to define what onpress does here in this case it's going to say history.push and uh let's see if we have yep we have history imported and what we're gonna do is we're gonna go to slash workout slash and we're gonna do the current date so i'm going to go like this and make this a bracketed function and let me so lets me save and reformat it so what i want is i would like to have the year here then the month and the day of of the workout so to do that we have the date and it is separated by dashes so i'm going to say date.split by the dash and so here we're going to say parts.date or sorry parts.0 for the year and then the month and then the day sorry this is your b1 this should be two okay so we haven't actually created that route but we can go ahead and click on this and it should take us to a different page and it should have the slash on it so something did not work um so i'm just going to see if this on press is getting called pressed all right and it is not being called so let's just go one deeper to the history card uh this and then our card click on that oh i forgot to pass on press to the touchable opacity here all right so let's click on this should take us to 2018 11 18. 2018 11 18 awesome so it's gonna be actually really easy to render the what goes here so let's first create the route for it so we're gonna go over to our routes create a new one here i'm going to say slash workout slash year and by the way this is how you do variables in react router so this is a variable in the url the year the month and the day and this is going to render the current workout component so in our current workout now we're going to take some things from the uh oops from the the url so now to tell react router that we have some things that we expect in the url we're going to say year string month string and day string now these may not be there if someone comes from the current workout so if we go back not that to routes you'll notice that we are rendering the current workout both on a route that looks like this and a route that looks like that so it's possible that someone came here with no route params on there so that's why i did undefined at the top here because they can possibly be undefined and so we can have access to those variables by saying match and then params and there's going to be a day a month and a year and then here now i'm just going to see if this throws an error um okay good i didn't know if it was going to complain um i didn't know it was going to complain because we have the we're destructuring these and they're undefined on the current ooh we didn't go to current workout slash current workout there we go okay yeah i didn't complain because the params are going to be undefined and we're destructuring them here so i didn't know if it was going to be upset about that but it looks like it's okay so i'm going to make a variable um is current workout so we could rename this uh thing because this really is just the display for the workout it may not be the current workout um so it's the current workout if there's not a year and there's not a month and there's not a day and so basically how this works now is we're going to do a check here so we're going to say is current workout if it is we're going to map through the current exercises otherwise we're going to get the day in history so we're going to say date key is equal to year dash month dash day and then we're going to look this up in our history so we're going to say root store dot workout store dot history and then use the date key and then we need to wrap this in parentheses so we're going to pick whether we're doing the current exercise or pick the exercises at a given day and we're going to map through those so just give you an idea here's all the exercises on this day um let's try this day and we can see we have just these three so nice the other thing is when i click on a workout actually that's good it should update automatically i think really the only last thing is when we save we can get rid of this random day when we save the workout we don't need to clear the current exercises if if we're doing a day in history so it is current workouts we're going to do this logic else we're going to just save the day in in history actually we don't even have to save it because it's automatically going to be updating it for us so that's awesome so only if we are working with a current workout do we need to actually save it in history otherwise we're going to be direct directly mutating the history i believe and there's no need to actually update it and so what i mean by directly mutating is when i hit this right two it's gonna actually save this and if i come back over here which day was i even working on was it this one yeah it's gonna remember the two in history and there's actually no need to hit save it's gonna save just goes back pretty much it's gonna remember that day so we can make changes to the day days in history now we can see the values all right so that's all i wanted to cover in this video we covered a ton quick recap is we went over fetching basically different workouts based on the date we have in the url and we use this to look up the key and i can count to log this date key so all we do is we take that and we can close this we don't need that right so in this case 1213 we look up that workout in our history object and then we display those exercises that we know the user did we even let the user update the days in history if they want to as well we're going to start off by making a floating action button now those are those little things you see in the bottom right corner of applications and you click on them they usually are used to add things and we're going to use that button to create workouts instead of putting that button all the way up here and then after that what we're going to do is we're going to start adding workout progressions or what i mean by that is after you do a workout you should increase the amount of work or the amount of weight you do the next workout so we're going to go through how you can increase that or basically create a workout plan all right so let's jump into the code for the floating action button so to start off we're going to create a new component in our ui here which i'm going to abbreviate fab for fab floating action button and i'm going to use our react hook snippet and i'm going to say our our style snippet as well and here we're going to say fab and the first thing is we're gonna have a touchable opacity and the touchable opacity is just so we can click on it and this will be the circle itself and then inside of the circle we're gonna have some text in our case we're just gonna have a plus sign um and then i'm just going to import that from react native so now i'm going to pass in the styles so i'm going to say style.fab and then here i'm going to say style styles.txt so we'll create a text style as well now for the text we'll start with that first because it's going to be pretty easy for the most part we're just going to say font size 18 or something like that and then for the touchable opacity we're going to do this in pieces so i think the first thing we want to start with is getting it located on the screen i'm going to give it like a width of 40 a height of 40. and then i'm going to say background color so we can see what it looks like we'll just make it pink and then we're going to do position absolute and then i'm going to position it at the bottom 10 pixels away and from the right 10 pixels away so let's take a look at what that looks like here um oh we need to actually render it so let's go to our workout history and render it at the bottom so let's say fab render that and see what it looks like um [Music] all right it does not match i think my disk here got messed up so i'm just going to delete it and run yarn watch again to just recompile it and give it a refresh oh you know what i think when i do that i'm gonna have to restart the client as well all right so what i expect uh for this is at the bottom we should have see like a little pink square so there we go cool now i notice it's not really 10 pixels from the bottom and the reason for that is our view that's the entire page is not flexing so i'm gonna create a style for it to have it flex so i'm gonna say container flex one and then this outermost style i'm going to say styles dot container so now this thing's going to be the entire page and so this can be 10 pixels away from the bottom because we need that outer container to take up the whole page all right so and we can see we can click on it as well next thing is we want this to be circular so we can use the same tactic as we did with the other circles and say border radius and half of the width slash height which in this case would be 20. so now we have a circle and then really the last piece of this is to make it uh i think we did our card is to add the shadow to it so i'm going to copy these three properties or these four properties that we used in our card to give it the shadow so shadow color and then some properties on the shadow and now we have a pretty nice looking button there uh the only other thing and by the way how this works is it kind of is floating above everything right so you can see it uh it kind of i don't know if we should have it so where it's kind of like over the scroll so maybe we should uh push it to the right like 20 pixels and do 20 pixels off the bottom to be more like there that might be better anyway you'll notice the button is going to be floating over the content all right and then really the last thing is to like get this plus sign centered in the middle there so we're going to say align items center justify content center all right now we have our plus now the plus to me maybe this is just an optical illusion looks like it's not dead center it might be to the left and right a little bit so if you wanted to you could add a little bit of margin on the text to the left and right to push it to like margin left two pixels margin bottom two pixels and that'll kind of push it a little bit and i think this looks a tad more centered in my opinion but it could just be an optical illusion all right so basically this button here we've now created a nice stylized one and we can click on it uh it's gonna do what our create workout button does up there so we can go ahead and remove that from our workout history so let's see what that was doing i'm gonna just copy the on press for that button and i'm gonna put that in the on press of this so we need to add an on press that way we can this works and uh we don't need this watch man i just have that on my clipboard all right and uh get rid of that and we're going to now in our props in the fab say on press and pass that to the opacity so now what should happen is i click on this it should take me to a workout page now we're gonna work on that next is what happens when that plus sign is pressed so first off we don't want to just push on exercises every single time if they're already in the middle of a workout we just can take them to the workout instead of creating a new workout so i'm going to do is i'm going to go to our workout store and uh oh by the way you guys just saw me do something that might have been confusing what just happened so i navigated to the workout store the way i did that i should explain that is i hit command or i guess control probably on windows and then i hovered over this variable and i can click on it and it'll tell me where it came from so you notice i clicked it once it took me to the root store and i hit command click again on the workout store and that's how i navigated to where the heck this came from so that's another way i commonly navigate besides just using the folder tree here um all right so yeah so i'm going to add a computed property on this so i'm going to say computed and i'm just going to say has current workout and this is going to be a boolean we're just going to return this dot current exercises stop length and uh this is going to be a boolean so i'm going to cast it to a boolean using the not sign twice so that'll cast this number into a boolean so basically if it's zero it's going to be false if it's larger than zero it's going to be true and all i'm doing is i'm checking if there's some values in current exercise so now what i can do is if rootstore.workoutstore dot has current workout want to do this or i guess the opposite so if there's not a workout so what's going to happen is we're not going to push on exercises unless um they're not in a workout currently and so the way we know if they're not a workout is if that's blank so uh did i ruin something oh yes i forgot to add the get property so we're just going to add the git name to that and then that allow us to access it like we are here where we don't have to call it as a function we can just access it as a field okay so now i'm going to go back over here and hit save that has a whole bunch of junk in it but if i click on this hit save or if i just like go back and you notice how i'm hitting plus every time we're not adding a whole bunch of workouts we're just looking at the same workout multiple times so the next thing is i want to fix up what we're actually doing for the current workouts so first off we should be doing a different workout depending on what day it is so the way we have it set up in our let's go back to our store is we have the the current workout day and i'm gonna set some default values so i'm gonna say it's gonna start as an a day and uh the current squat weight i'm going to say 45 and basically you're going to just start with just the bar which is 45 pounds and then barbell row and both the deadlift are going to be kind of hard to start with just the bar so we're gonna say uh let's maybe hopefully they have like some bumper weights they're like 10 pounds or something so we'll say 65 pounds you'll start with okay so now with these values this is what i'm going to increment and the current squat value and all that stuff is what we're going to persist and as the user is working out we're going to increment these numbers so the way we're going to do that is first off we're going to hinge on that day so here i'm going to say rootstore.workoutstore and we're going to say last workout type and we're just going to inverse it so we're going to say we're going to look at what the last workout day was if it was a then we're now going to do a b and vice versa so that should be b that should be a this way so all this does is when we hit the plus it's now going to toggle between a and b um because we're checking if it's a last time then we now want it to be a b this logic may need to happen somewhere else or maybe i should reword this and say like what the current workout type what is um so if the last workout was an a the next one would be a b no this makes sense i think all right so that's going to switch between the workout types the next thing is to actually increment the weight and use that here so instead of doing these weights we're basically going to check what day it is and do a different condition so again i'm going to be hard coding this here for simplicity's sake but ideally you should probably put this in some kind of array of exercises or whatnot or maybe a condition of some sort so we're going to say last workout type if it was equal to b that means today is an a day and on a day you're going to do this set of exercises oh and this this this stuff should go inside of there all right so we're going to say do these set of exercises and we'll paste that in there all right so so what we're going to use is the current values as well so we're going to say root store dot workout store dot and then we're gonna grab all these current values current barbell current bench deadlift squat and overhead press and i guess i'll move this outside of here all right so the name of its squat number of sets and then the weight here is going to be the current squat weight current bench press weight and i'm going to just create a const empty sets because we're going to basically reuse this in multiple places and now what i'm going to do here is i'm going to say dot dot empty sets and what this is going to do is it's going to basically just create a new instance of this array i don't know if we would have a problem with having the sets like references to the same array so that's why i want to create a new array each time just to be safe all right and then down here we're going to say actually deadlift is special so we'll just hard code it like that current deadlift and then at the bottom here i'm basically going to just say i'm going to increment each one by two pounds or 2.5 pounds i guess so squat 2.5 and then bench press and then deadlift so basically what's happening is we're going to do these exercises and then we're going to increment the weight for next week when we do them and then we're going to basically copy this and do the same thing but with different exercises on the b day so again you can see where we kind of have some duplication of things where it may be simpler to switch this out with some kind of looping so we're gonna be doing an overhead press and a barbell row but we still do squat so barbell row empty sets and then here current barbell row and then we're just rinsing repeating overhead press here and we're pretty much done i think now um with this switching so let's see what we just accomplished so now when i hit a press on this we'll get squat bench deadlift and uh let's see what poundage we're at let's save this so now squat overhead press barbell we're at these pounds save it and if we look at what we're gonna do next week squat is oh you know what it's 2.5 on each side so that really this should really be five that's how much i want to increment by but you'll notice how the squat incremented there and we got a new set of exercises so now it's going to oscillate between these exercises each week and we slowly increase the weight of them and what not anyway guys i think that is the end of us adding features to this application in the next video what i'm going to do is make sure the app works the react native one and at least on the ios emulator and then also deploy this to netlify now there's a ton of things that we could add to this to make it better and a ton of different features so i hope this gave you a good introduction and how you can get started with this and a good starting framework and i invite you encourage you to start adding some features onto this get an idea of how it might work switch up the styles of things and kind of make it your own workout application customize the different lifts and set up if you work out to your routine we're going to go over how we can deploy our react native web application to netlify so this is the website and to start off we're going to be making three changes to the project for the purposes of getting this to work to deploy the first is in our common package in the package.json we want to add a script called post install so this is a special npm script that gets run after someone does a yarn install or an npm install so basically what happens is when the uninstall is going to get run it's also going to build the project in this case it's just going to generate the dist folder so whenever this project is installed the dist folder for common is going to be created and the reason we want this is because we're going to be building the application on netlify and it's going to need to be able to access this dist folder so it needs to be built so that's how we're going to trigger it secondly we're going to go to our web package and we're going to be running the build command and we need to add the cross and the skip pre-flight check to beginning of it to get it to work similar to we had we did it for the beginning of start here and the build command basically what that does is it's going to take our react application here and it's going to spit out a build folder with the basically compiled code or transpiled code that's minify and all that fun stuff and then lastly to get our routing to work on netlify since we are using react router in the public folder of our web package we have to create a special file called underscore redirects so this is something that works with netlify and basically we're saying any time zone goes to a path we want to redirect them to the index.html file basically all this does is it says allow react router to do routing for us all right so those three after you make those three changes i went ahead and committed the code and then i pushed it up to github now the branch that i'm working on i called it prod let's just clear that so i called it prod and i committed and pushed up to this prod branch now i said we're going to deploy to netlify i went overhead and i already created a netlify account i have a netlify project that i created you're going to want to do the same thing i connected my github repository but you could do git lab if you want to as well after that i chose the repository that i want to link it to because basically what we're setting up here is whenever you push to the github or get lab repo it's going to grab that code from netlify or netfly is going to grab that code is going to build it and then it's going to deploy it and then after you pick a repository it's going to ask you for some build options so these are the build options that you're going to want to do your build command is going to be the following so basically we're just going to run npm run build inside of the uh web package so you just cd into the web package and then you run npm run build and then here we just specifying the directory where our compiled code's going to be or the once it's built in our case it's going to be in packages web slash build now another important thing is i went ahead and just said the latest version of yarn as a build variable so i said yarn underscore version 1.13 and basically what this does is it tells netify to use this version of yarn i just make sure to do that so it doesn't have any problem with the arm workspaces and i just grabbed that version off of the latest one that i have on my computer all right so after i did that basically the site deploys and that's pretty much it you can go to the poise log you can see the the ones that hopefully published my first try it failed but you can see the logs if you have any problems you can go and see what error you have and you can try fixing it but after that it's going to deploy your site you can even give your site a name and set it to https if you want to i can see my site here react native web workout is what i named it so this is live in production anyone can access this so if you want to you can come access it too and the data is all stored in local storage so everyone's going to get a different version and we can now do our workouts and whatnot and save them anyway that is how you deploy it to netlify with react native web you'll notice it's not too much different from a react project it's pretty much the exact same the only difference is really stuff to deal with react router and yarn workspaces now i also mentioned that i check out the app and i spent about an hour trying to get it working but i just ran into basically the same sim link problem and just having problems with the dependencies i'm not really sure the best way to set up since we did react native cli i'm not really familiar with how to get yarn workspaces working well with it i've always used expo before so instead of just trying tons more and more workarounds i was kind of getting tired of trying it um especially because i saw that facebook has uh made a little announcement about how they're going to tackle the sim links problem and estimate about a month away uh so this issue was created two days ago it looks like um so about a month from now sim link should be working so i was like i don't even feel like trying to get some links workarounds i'm just gonna go ahead and forget about it and wait a month until this is complete anyway if this video is uh if you're watching this like a month from now check the date sim links may be working and you can try out the app um using that but for now i'm not going to worry about it we got the web version of it up and rank so i'm happy with that and this is the one that i wanted to see the most anyway anyway that is the end of this workout series i hope you guys liked it and until next time i'll see you guys later you

Original Description

Learn to use React Native for Web to create a workout app that works on Android, iOS, and the web. The app uses Mobx, Typescript, React Navigation, React Hooks, AsyncStorage / Localstorage, and more. Once the app is complete, you will learn how to deploy it to Netlify. 💻 Code: https://github.com/benawad/react-native-web-series ❤️ Try interactive React courses we love, right in your browser: https://scrimba.com/freeCodeCamp-React (Made possible by a grant from our friends at Scrimba) ⭐️ Contents ⭐️ ⌨️ (0:00:00) Setting Up a React Native Web Project ⌨️ (0:09:04) Setting Up React Native Hooks ⌨️ (0:15:03) Setting Up a React Native Web Monorepo ⌨️ (0:28:24) Configuring React Native for Yarn Workspaces ⌨️ (0:39:58) How to use Mobx with React Hooks ⌨️ (0:49:15) Navigation in React Native Web ⌨️ (1:03:28) Styling a Component in React Native Web ⌨️ (1:27:40) Mobx Root Store ⌨️ (1:45:20) Workout Timer with Mobx ⌨️ (2:11:20) React Router with React Native Web ⌨️ (2:22:45) How to Persist Mobx Stores ⌨️ (2:30:47) Storing and Displaying Workout History ⌨️ (2:54:33) React Router Params in React Native Web ⌨️ (3:17:30) Floating Action Button React Native Web ⌨️ (3:34:45) Deploy React Native Web to Netlify ⭐️ Links: ⭐️ 🔗 https://stronglifts.com/apps/ 🔗 https://github.com/necolas/react-native-web/blob/master/docs/guides/client-side-rendering.md 🔗 VSCode settings used: https://gist.github.com/benawad/1e9dd01994f78489306fbfd6f7b01cd3 Course from Ben Awad. Check out his YouTube channel: https://www.youtube.com/benawad97 -- Learn to code for free and get a developer job: https://www.freecodecamp.org Read hundreds of articles on programming: https://medium.freecodecamp.org And subscribe for new videos on technology: https://youtube.com/subscription_center?add_user=freecodecamp
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from freeCodeCamp.org · freeCodeCamp.org · 0 of 60

← Previous Next →
1 React: Production Server Setup Part 2 - Live Coding with Jesse
React: Production Server Setup Part 2 - Live Coding with Jesse
freeCodeCamp.org
2 cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
freeCodeCamp.org
3 Browser history tutorial - Beau teaches JavaScript
Browser history tutorial - Beau teaches JavaScript
freeCodeCamp.org
4 Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
freeCodeCamp.org
5 React: Parameterized Routing with Next.js - Live Coding with Jesse
React: Parameterized Routing with Next.js - Live Coding with Jesse
freeCodeCamp.org
6 React: Dealing with jQuery Issues - Live Coding with Jesse
React: Dealing with jQuery Issues - Live Coding with Jesse
freeCodeCamp.org
7 setInterval and setTimeout: timing events - Beau teaches JavaScript
setInterval and setTimeout: timing events - Beau teaches JavaScript
freeCodeCamp.org
8 Browser and Device Testing - Live Coding with Jesse
Browser and Device Testing - Live Coding with Jesse
freeCodeCamp.org
9 Last Minute Updates - Live Coding with Jesse
Last Minute Updates - Live Coding with Jesse
freeCodeCamp.org
10 Post Launch Updates - Live Coding with Jesse
Post Launch Updates - Live Coding with Jesse
freeCodeCamp.org
11 React: Setting Up Google Analytics - Live Coding with Jesse
React: Setting Up Google Analytics - Live Coding with Jesse
freeCodeCamp.org
12 React: Masonry Layout - Live Coding with Jesse
React: Masonry Layout - Live Coding with Jesse
freeCodeCamp.org
13 Load Balancing Digital Ocean Droplets - Live Coding with Jesse
Load Balancing Digital Ocean Droplets - Live Coding with Jesse
freeCodeCamp.org
14 try, catch, finally, throw - error handling in JavaScript
try, catch, finally, throw - error handling in JavaScript
freeCodeCamp.org
15 Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
freeCodeCamp.org
16 Graphs: breadth-first search - Beau teaches JavaScript
Graphs: breadth-first search - Beau teaches JavaScript
freeCodeCamp.org
17 React: Masonry Layout Part 2 - Live Coding with Jesse
React: Masonry Layout Part 2 - Live Coding with Jesse
freeCodeCamp.org
18 React: WordPress API Live Search - Live Coding with Jesse
React: WordPress API Live Search - Live Coding with Jesse
freeCodeCamp.org
19 Creating WordPress Custom Post Types - Live Coding With Jesse
Creating WordPress Custom Post Types - Live Coding With Jesse
freeCodeCamp.org
20 Dates - Beau teaches JavaScript
Dates - Beau teaches JavaScript
freeCodeCamp.org
21 Miscellaneous Front End Updates - Live Coding with Jesse
Miscellaneous Front End Updates - Live Coding with Jesse
freeCodeCamp.org
22 Merging a Pull Request from GitHub - Live Coding with Jesse
Merging a Pull Request from GitHub - Live Coding with Jesse
freeCodeCamp.org
23 React + Prettier + Standard JS - Live Coding with Jesse
React + Prettier + Standard JS - Live Coding with Jesse
freeCodeCamp.org
24 React: Sortable Responsive Table - Live Coding with Jesse
React: Sortable Responsive Table - Live Coding with Jesse
freeCodeCamp.org
25 Geolocation Sorting by Distance - Live Coding with Jesse
Geolocation Sorting by Distance - Live Coding with Jesse
freeCodeCamp.org
26 Tradeoff Matrix - Agile Software Development
Tradeoff Matrix - Agile Software Development
freeCodeCamp.org
27 The Definition of Ready - Agile Software Development
The Definition of Ready - Agile Software Development
freeCodeCamp.org
28 Getting first React job without experience - Ask Preethi
Getting first React job without experience - Ask Preethi
freeCodeCamp.org
29 React: Google Analytics Click Tracking - Live Coding with Jesse
React: Google Analytics Click Tracking - Live Coding with Jesse
freeCodeCamp.org
30 Submitting a PR to an Open Source Project - Live Coding with Jesse
Submitting a PR to an Open Source Project - Live Coding with Jesse
freeCodeCamp.org
31 Should I go back to school to get CS degree? - Ask Preethi
Should I go back to school to get CS degree? - Ask Preethi
freeCodeCamp.org
32 Hero Section CSS Changes - Live Coding with Jesse
Hero Section CSS Changes - Live Coding with Jesse
freeCodeCamp.org
33 Working Agreement - Agile Software Development
Working Agreement - Agile Software Development
freeCodeCamp.org
34 A day at Pennybox with Co-Founder Reji Eapen
A day at Pennybox with Co-Founder Reji Eapen
freeCodeCamp.org
35 React: Sorting and Filtering Data - Live Coding with Jesse
React: Sorting and Filtering Data - Live Coding with Jesse
freeCodeCamp.org
36 React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
freeCodeCamp.org
37 React: Building a New UI - Live Coding with Jesse
React: Building a New UI - Live Coding with Jesse
freeCodeCamp.org
38 Definition of Done - Agile Software Development
Definition of Done - Agile Software Development
freeCodeCamp.org
39 Getting started with jQuery (tutorial) - Beau teaches JavaScript
Getting started with jQuery (tutorial) - Beau teaches JavaScript
freeCodeCamp.org
40 Making a React Blog with WordPress Content - Live Coding with Jesse
Making a React Blog with WordPress Content - Live Coding with Jesse
freeCodeCamp.org
41 React, NextJS, CSS - Live Coding with Jesse
React, NextJS, CSS - Live Coding with Jesse
freeCodeCamp.org
42 jQuery events - Beau teaches JavaScript
jQuery events - Beau teaches JavaScript
freeCodeCamp.org
43 React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
freeCodeCamp.org
44 React: Working with API Data - Live Coding with Jesse
React: Working with API Data - Live Coding with Jesse
freeCodeCamp.org
45 React: Refactoring Components - Live Streaming with Jesse
React: Refactoring Components - Live Streaming with Jesse
freeCodeCamp.org
46 jQuery effects - Beau teaches JavaScript
jQuery effects - Beau teaches JavaScript
freeCodeCamp.org
47 More React Refactoring - Live Coding with Jesse
More React Refactoring - Live Coding with Jesse
freeCodeCamp.org
48 animate in jQuery - Beau teaches JavaScript
animate in jQuery - Beau teaches JavaScript
freeCodeCamp.org
49 "Finishing" My React Site - Live Coding with Jesse
"Finishing" My React Site - Live Coding with Jesse
freeCodeCamp.org
50 Starting a New React Project (P2D1) - Live Coding with Jesse
Starting a New React Project (P2D1) - Live Coding with Jesse
freeCodeCamp.org
51 React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
freeCodeCamp.org
52 The Agile Manifesto - Agile Software Development
The Agile Manifesto - Agile Software Development
freeCodeCamp.org
53 jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
freeCodeCamp.org
54 React Project 2 Day 3 - Live Coding with Jesse
React Project 2 Day 3 - Live Coding with Jesse
freeCodeCamp.org
55 The INVEST approach to product backlog items
The INVEST approach to product backlog items
freeCodeCamp.org
56 React Project 2 Day 4 - Live Coding with Jesse
React Project 2 Day 4 - Live Coding with Jesse
freeCodeCamp.org
57 Chickens and Pigs - Agile Software Development
Chickens and Pigs - Agile Software Development
freeCodeCamp.org
58 React Project 2 Day 5 - Live Coding with Jesse
React Project 2 Day 5 - Live Coding with Jesse
freeCodeCamp.org
59 jQuery: add and remove DOM elements - Beau teaches JavaScript
jQuery: add and remove DOM elements - Beau teaches JavaScript
freeCodeCamp.org
60 React Project 2 Day 6 - Live Coding with Jesse
React Project 2 Day 6 - Live Coding with Jesse
freeCodeCamp.org

Related Reads

Up next
How to Speed Up Your WordPress Website with WP Rocket ⚡Tutorial 2026
Matt Tutorials
Watch →