Setting up vite, React, TypeScript, eslint, prettier, vitest, testing-library and react-router

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello friends welcome to coding garden in this video i'm going to show you how to set up a react and typescript app with veet uh but we're not just going to set up a basic app we're also going to get all of our developer tooling set up as well so once we get the basic app up and going we're also going to set up eslint which makes sure that we write consistent code we're also going to set up the eslint airbnb config which is more opinionated in more rules about how we style and structure our code and then we're also going to set up prettier which has a lot of opinions on how to format our code after we get all of that working then we're going to set up testing and specifically unit testing on the front end this video is just starting but you've probably been watching youtube all day look away from the screen take a quick stretch and then we'll get right into it so lastly we will set up unit testing so specifically we're going to use this library called v-test which is a blazing fast unit test framework we're going to combine that with js dom which is a dom in pure javascript and then we're going to use this thing called testing library going to combine all those together i'm ready to get some nice unit testing for our react app and then lastly we'll just set up a little react uh router let's go so first step is to generate an app using veet uh if you go to vtjs.dev you can read more about it and i am specifically going to run this command so i'm using npm if you're using yarn or pnpm just follow those commands instead but i'm going to run this command right here and it's going to ask me some questions so i'm going to call this react ts app i want react react ts so this will automatically set up a ts config for me um and then now if we go into there we can take a look and while we're taking a look i'll go ahead and do an npm install to get all of the dependencies installed but if you take a look at the package.json you can see we have a dependency on react and react-on that's so that we can write react uh we have a dependency on the types so we can use typescript with them and then we have a dependency on the veet plugin for react a dependency on veet and a dependency on typescript all of these are dev dependencies so these are these dependencies are only working for us locally so that we have a good developer experience great you can see the scripts we have npm run dev which will just run veed npm run build which will build and bundle our veet app and then preview which i believe will preview the built version of the app um we can see that we do get a ts config and there's there are two ts config so the tsconfig.json uh with like lib dom etc is the typescript config used by our react code because that react code is going to need to get turned into javascript that can run inside of the web browser and this config specifically does that this one is for veet itself so we can configure veet with typescript so we can see we have this veetconfig.ts but vt is running on our machine with node.js so it needs a slightly different ts config so that's why we have two ts configs and then we also have this index.html so this is essentially our entry point and you can see how this stuff is working so veet has a reference to our main tsx file um and this is kind of weird right you've probably never seen an html file mixing tsx because usually tsx is typescript with jsx but that isn't referenced directly in each html it's actually like bundled and then like your react app is mounted but veet works in a very interesting way so if our dependencies are installed if i do npm run dev we should get a veet app to spin up it might be on a different port for you but i have a bunch of stuff on my machine so it just gives me the first available port here we go we have a veet app but if we look at the source code of the page we can see some interesting stuff going on so you can see right here it has a reference to source main.tsx but when i click on it i see some weird stuff so essentially what veet and es build behind the scenes have done is when the web browser requests this file it actually transpiles it into javascript on the fly so if you look at the actual source main.tsx file it's your pretty standard react setup right import react import our app component and then mount it in the dom right there um but the way veet handles this is basically when that file is requested on the fly it transpiles it and then that's what's get loaded into the browser so the code we write gets looks like this but when it runs through typescript and es build it ends up looking like this which is cool um so yeah that's that's that html right there we just reference that one file it loads it in and then veet handles the rest so that's our main entry point you can see that it's referencing index.css these are just global css styles while we're in here i'm just going to go ahead and rip them out because we won't have any any basic css to start if we take a look at the app.tsx this is our main main component let's also rip some stuff out of here too so we can see that it's importing app.css uh this is still technically global css even though it's being imported like this so for now i'm actually just going to straight up delete app.css as well and then let's reconfigure this component to get rid of all the stuff we don't need so i don't want that react logo for now we're not going to have use state i'm literally just going to have a div that says hello world like this uh and so this is our basic react react app and if we go back over here boom we see it's it's nice and ugly with uh just like that default uh times new roman font awesome uh and then i'm gonna go ahead and get rid of this react.svg because we're not using it and right now uh if you look in the index.html it is referencing uh veet.svg as the the favicon favicon that favicon referencing it as the icon but i'm going to get rid of that if you want to add a favicon you could just put one in the public folder and replace it so i'm going to get rid of that as well in the past people have asked me what's the difference between that assets folder in that public folder uh here is my answer for that if you have uh assets that need to be bundled in some way so they need to run through some loader that will minify them or transform them in some way it makes sense to put them in the assets folder if you have assets static assets that don't need any sort of processing you can just put those directly in the public folder and these are going to get copied over to your build all right that is it for generating the app and in the quick preview um next up we are going to configure eslint and all of the associated uh formatting and linting tools as well yeah and so that's the other cool thing is like uh that's the nice thing about veet is the uh hot reloading is blazingly fast and unironically so so there's my um my little react app over there watch this watch how fast so i'm going to press command s boom instant instant um right ready command s boom so like veet hot reloading and page refreshing is insane and it's all because of this thing es build it's using this under the hood um yeah so eveet is essentially combining es build and roll up into a really fast and really good developer experience yeah wow so to set up eslint the first thing we need to do is install eslint as a dev dependency so i'm going to go ahead and kill the vtap if i do npmi dash capital d eslint that'll install eslint as a dev dependency and if we take a look at our app and we take a look at that package.json we should now see eslint in our dev dependencies good to go all right now that we have eslint installed as a dev dependency we can do npx eslint dash dash end it so again when you do npx it's going to look in the node modules folder so because we just installed eslint it'll run it from there and then dash dash init is their command line tool so that way we can generate a basic configuration so for now i'm just going to choose check syntax and find problems after we get this initial base set up we're going to install some other plugins to get the configuration that i like we are using imports and exports we're using react we are using typescript our code is running inside the browser because this is a react app and the config file will be in the javascript format so you can see that this is also going to install these dependencies so plugin react es typescript eslent plugin typescript eslint parser this allows typescript to work in conjunction with eslint and i'm using npm so we can install these so after running that we should have a basic eslint config you can see right here this eslintrc.cjs and you can see that it's extending eslint recommended plug-in react all of that good stuff but there are a few other plugins that i want to install so first of all uh airbnb so the airbnb style guide is a style guide released by the airbnb company that describes how they like to write javascript and react code and it's just a bunch of their opinions because there's a lot of ways to do it a lot of different ways you could uh write a functional component or a lot of different ways you could do various things and so they have a bunch of rules where they've defined all of that ahead of time and i want to pull those into my at my eslint config so that way i don't have to configure those rules manually and essentially by installing this we are going to get all of those default rules so now to install eslint config airbnb we're going to run this command because there are a few other dependencies we need along with eslint config airbnb you can see when we generated our eslint config we did get eslint plug-in react and the typescript eslint uh plug-in and parser but we didn't get things like eslint plug-in react hooks esl plug-in jsx11 a11y we didn't get any of these so if we run this command it's going to install eslint config airbnb and all of the things that it depends on so i'm going to copy that command from here and run it and uh install puredeps is specifically a command line tool that's going to find those peer dependencies and then install them as well so you can see now what it's doing it's installing eslint config airbnb es lint which we already had eslint plug-in import es and all of these other things so it installed all of those and then now we can see we have a bunch more uh plug-ins in here as well awesome so now that it's installed we can add it to our config so specifically in the extends section of our eslint we want to add airbnb and airbnb hooks so if we go over to our eslint here i'm actually going to get rid of eslint recommended and i'm going to add these these in airbnb essentially overrides eslint recommended airbnb has all of the things all of the rules all the things i want and need so once i put it there we're not extending from eslint recommended anymore and you can see i instantly got the moment i saved that i got some red squiggly lines and you can see that expected indentation of four spaces but found eight so the airbnb airbnb config enforces a i believe a two-space tab um and so now that i have that if i do command-shift-p eslint fix all auto-fixable problems now it's taken the default rules that airbnb likes and prefers and it's applied that to this specific file so that's great next up we need these rules to also support typescript so there's a plugin for that this plugin eslint config airbnb typescript so i can install it as a dev dependency here you can see in uh their description they say hey you need that thing we just installed eslint config airbnb and then they also say that you need eslint plugin and parser which we do have if you remember when we generated our config we all we got these two things when we told it that we were using typescript so we already have those we only need to install this so now i will do an mpmi capital d eslint config airbnb typescript and then now we get something else that we can extend and we specifically are using react so we want this airbnb typescript this is saying if you're not in a react app you would do it this way but we want that and so if we go back over to our config right here we're going to do airbnb typescript so now we have rules for our typescript files as well so you can see now that i added airbnb typescript we're getting this ugly error right here but essentially what we need to do is down here in our parser options we need to tell eslint how to or where to find our typescript config and if you look in the docs over here they tell us that we need to do this so we need to add this project section to our parser options make sure that you're not adding a new key make sure you go down to where the parser options are and you put this there now when you save this this should work let's actually reload the window so if you do command shift p reload window that's gonna reload our our typescript server and our eslint server just to make sure everything is fresh and like nothing's stale so we didn't see that error pop up which is great but now we have another error we need to fix if we highlight over this this is telling us that um we have the parser option set but it does not match this specific file so basically right now we told it hey that's how we configure typescript but what it's saying is hey your config file isn't being looked at by typescript so we need to go to our typescript config and tell it to uh that we should be looking at this specific uh file here so if we go to our ts config.json there's this section called include and we can add as many things as we want in here i'm essentially just going to add a new element that is the name of my eslint file eslintrc.cjs so now specifically eslint uh sorry uh typescript is pointed at that file and then now uh eslint is pointed back at typescript so now these two can work well together and again i'm going to have to reload the window but that should pick up that setting so if we give it a second and um also you can see this down here so if you see these these spinning things that's the the javascript language service and everything else if all of that settles and you don't see any errors then you know that we've we've fixed them all so at this point we've we've connected together our eslint config and our typescript config and we are now using the airbnb rules so at this point we can see what we get so specifically i have the extension eslint installed so if you search the vs code extension store for eslint you want to make sure that you have it installed and enabled but now because we have those two config files if we look at for instance our main.tsx we get some red squiggly lines uh and if we hover over these this says uh missing semicolon so i like to have semicolons in in my javascript code and specifically we extended from the airbnb rules and there's a rule in the in here that says semicolons are required so um i like that rule i'm going to use it um but you could technically turn that rule off or say you don't want semicolons but you can see there's there's lots of errors and i could manually go in and do like this and then like this but when there are errors that eslint can automatically fix we can run a command for that you can see this is this is complaining about a missing comma but if you do command shift p and then search for eslint and choose fix all auto fixable problems anything that's auto fixable in this one file will get fixed so you can see now instantly it added the semicolons where it needed and it added the comma good to go uh we only have one other file we need to worry about which is this app.tsx i'm going to run fix all auto fixable problems but then we run into an issue that we we need to fix as well so if you hover over the div here this is saying react must be in scope when using jsx now this used to be the case uh for older react but with the latest version of react you actually don't need to import react it used to be that you had to do something like this import react from react and then you didn't even use it but uh the latest version of react has been updated so you don't need to do that but we need to tell eslint that we don't need to do that uh we're actually going to disable this rule and i'm going to show you a few different ways to disable the rule but essentially if you come across a linter rule that you don't agree with or you want to disable these are the ways to go about it so inside of vs code if you do command period you will get a few options first you have disable this rule for this line and if i do that it's going to add a little comment right there and now i don't have to worry about that linter rule but everywhere that happens in my code base i would need to add that comment you could also do disable for the entire file and that will put it at the top of the file and now any other code that's not adhering to that role won't complain so i want to disable this rule for the entire project so what i can do is take the rule name so usually what i'll do is if i know there's something that i want to go disable for the whole project first i'll just do it like inline but that will give me the rule name so that i can copy it to put into my config so i'm going to grab this rule name and then remove this comment and then now if i go over to my eslint rc there's a section called rules and we can now take rules and disable them so i'm just going to put 0 right there and that'll turn that rule off so now anywhere else in my code base where that was happening it won't throw an error anymore so at this point we have eslint configured which handles all of the code style and and things like missing semicolons or using single quotes versus double quotes those kinds of things now we're going to install prettier which handles our code formatting so an example i have of that is let's say you have some jsx element it has a bunch of props or attributes on it right now this isn't breaking any eslint rule because the line isn't long enough i think there is a rule like if a line yeah so at this point if i pasted it twice now the line is too long but um there's a rule for really long lines but there's not a rule about how to format for instance like uh html elements in their properties or jsx elements in their prop in their properties if we install and configure prettier to work with eslint we can get those rules which also format our code which is a good thing um so let's get going for that the first thing we'll need is prettier we're going to install that as a dev dependency we're also going to use eslint config prettier which essentially disables rules we've enabled which would conflict with prettier and then eslint plug-in prettier which will make it so that um all of the the prettier rules are working in conjunction with all of my eslint rules so i need all three of these dependencies as dev dependencies so i'll run this install good to go and then now we need a configuration file so if you look on the prettier docs there's this configuration file docs and i'm going to use a a cjs version you can see there's a lot of different ways to configure it i'm specifically going to do it this way very similar to how we have our eslint rc.cjs so new file.prettierrc.cjs and inside of that i'm going to add the basic prettier settings and in my case i prefer a two-space tab and i prefer semi-colons they should be required and i also prefer single quotes single quotes um instead of double quotes and those settings are very similar from the airbnb config as well so we have those settings good to go uh now we need to um extend our configuration and add the the prettier plugin so in the the prettier docs there's a section on integrating with linters we specifically are going to use this and we did install this eslint plug-in printer so if you go to their docs they tell you how to do it so we need to add it to the plugins section so if we go to our eslint rc file scroll down to the plugin section we're going to add prettier right here and then in the docs they mentioned you could add the prettier rule but we also installed this eslint config prettier and what we can do is we'll add this to our extends section and that is automatically going to enable enable the prettier rules so i'll copy this and then in the extends section you want to make sure that this is the very last one so essentially prettier has some rules that might conflict with all of these other configs that we're extending and so by adding that as the last one we make sure that all of these other things work in conjunction with our prettier rules so at that point i saved it um and you can see it's complaining so this is saying replace four tab with eight tabs i think so if i do eslint to fix a lot of physical problems um right now i believe it has the wrong config and i just need to reload the window so right now this file is telling it that i have a tab width of two printer doesn't know that so i'm going to do reload window and hopefully it'll pick up those settings and realize that it told me to do the wrong thing um let's see yeah so now it's like oh you want a two-space tab because it's like delete two tabs and so now if i run eslint fix all autofixable problems it gets it makes it a two-space tab so just be sure after adding all of these configs and setting everything up you do a reload window or at least just close vs code and reopen it to make sure that it's picking up all of your settings so that file is good to go but now watch what happens in here so in here we're now getting an error that it's like hey you need to replace this with tabs and stuff and such so if i do eslint fix all auto fixable problems it now pulls those prettier rules in and it's able to format my code um along with doing things like adding missing semicolon so if we go back to that like let's say i was missing some semicolons let's say i had that on that line and that on that line for some reason if i run eslint fix all autofixable problems boom all of that stuff is is added according to my config so we're good to go there next up let's set up testing so specifically we're going to use this unit test framework called v-test it's from the same creators of veet which is what we used to scaffold out our basic project and also what we're using to actually run our app so when we run npm run dev veet kicks in spins up a dev server and then we can actually visit our react app there and right now we have that little dinosaur input which is fine uh but we're gonna set up testing with v test so if we go through the getting started they show us how to install this first we're gonna need v-test as a dev dependency so let's do that so npm install dash capital d v test so now that we've installed vtest we can configure it we can see here that on their main page they're mentioning that we would create a v vtep config that would be separate from our feet config but i did take a look at their example so they have a lot of examples set up with various test frameworks and in this one they just use a singular veet config so i'm going to set it up in a similar way i'm essentially just going to going to copy this config and this config will replace my existing veetconfig so if i go in here you can see that they're importing similar things plug-in react we have our plug-ins with react the main things that we're adding and actually instead of copying the whole thing i'll just copy the pieces that we need so specifically we need this piece here and then we also need this test section and you can see uh it says environment js dom vt v test is already set up to use that if we specify it so now that i've specified that we're going to be using jsdom you can see that i am getting an issue here where it's like we we don't know how to parse this file and this is the same issue we had earlier with our eslint rc config so if i go to my tsconfig.json i need to add my veet.config.ts right here so that typescript knows that it should be looking at that file and then if i open my vconfig backup if i reload the window it should stop complaining about that so now eslint is working typescript is working i'm getting some linter errors first let's run eslint on this file that adds semicolons and missing commas um and then the next issue here is eslint is complaining about veet being a dev dependency uh veet should should be a dev dependency i don't want to move it so i'm actually just going to ignore this error for this one file so if i do that no extraneous dependencies um i'm only ignoring that in this file if i have extraneous dependencies in my actual react code that is something that i want to fix but here i don't need to worry about that so at this point we have v test configured inside of our veet config and now i need to create a file that will run at the beginning of every test run you can see right now it's referencing source setup i'm going to create my own file and call this setup tests and in the source directory i'll specifically create that file called setuptests.ts and in here is where i can do all of my specific setup that will run before any of my test runs all right next up i need to set up testing library so v test is our test runner it's the thing that will find all of the test files in the directory and then run those specific tests so when you look at the test later we're going to see describe it expect all of those are coming from veet but we specifically need some some utilities that are going to allow us to specifically test react components and testing library is really great for that so if we go into their docs click on frameworks and go to react to testing library this will show us how we can get it set up so we specifically want at testing library react so i'm going to install that as a dev dependency the other dependency we will need is specifically uh jsdom expectations so uh we saw in the config our environment is js dom jsdom is a library that essentially allows you uh to do dom-like things without a web browser and that's what we're doing in these tests they're specifically testing react components in isolation so they need some sort of dom environment but the expectations built into veet do not have all of the nice things that come along uh with the testing library expectations so there specifically is a a package called testing library just dom and it gives you these expectations so now when we do expect we'll get access to things like to be disabled to contain element to contain html two have class these kinds of things these are more like dom specific expectations and so by installing this library uh we'll get access to those in our expectations as well so i need to install testing library react and then testing library just on both as developer dependencies cool so now that we have these dependencies we need to set it all up and there's this really good blog post from uh marcus oberliner who talks about setting up just on with vtest which is what we're trying to do right now so we just installed it as a dev dependency but now inside of our test setup we can add all of these extra matchers so over here in setup tests i can run this code let's run our linter really quick but we're specifically pulling in expect from v test and then we are extending it with all of those js dom matchers that i just showed you this is probably the error we had earlier so no extraneous dependencies i'm going to add this for the entire file because these are dev dependencies and specifically when i'm inside of my test files those are allowed to have extraneous dependencies because it's not the code that's going to be running uh when the uh when the app is deployed all right now we have all of our tests set up let's create our very first test so in the source directory here i'm going to create a file called app.test.tsx so this is one of the things that i like to do other people have different opinions but i like my tests to sit right next to the file that i'm testing so you might see other people have a folder called tests and then they put all of their tests in there for me it's nice to have the test file right next to the file that you're testing because then you don't have to look all over the place to find it and so i'm going to put it right there and then the first thing we need are a render and screen so we'll pull in render and screen from testing library react so render is allow going to allow us to render components and screen is going to allow us to to inspect and poke at those components to pull things out and then test against them we're also going to need describe and it from vtest now you technically don't have to import these um but i like to be explicit about it like in in other testing frameworks uh describing it or just like magic variables i like that we're specifically importing them and then we should get some autocomplete as well so describe is the way that we set up a test suite so a suite is going to contain multiple tests one or more tests and so here i'm going to say we will describe our app and then you pass it a callback and then inside of that callback you have multiple tests and you test with the it keyword so i'll say it renders hello world and then inside of it is where we will write our specific test so in testing there's this three parts that we typically follow which is arrange we arrange and get our tests set up our unit test set up we act that is do the things that a user would do with the specific component and then we expect we check to see that after the user interacted with the page we have the expected outcome so all of our tests are going to take this format we might not always have an act which i'll show in this case we're not going to because it's a very simple test but now we can do the testing so i'm going to import app from [Music] uh app so now we have that specific component and we're going to do our arrangement and in this case we just need to render it so i just pass the app component into render and now i can use screen to interact with it so for now i'll do let's expect that screen dot get by roll so i'm specifically going to be checking for an h1 element on the page so i'm going to get by roll i specifically am looking for a heading because that's what an h1 is and i want the level to be level one so that will find an h1 on the page if it is there and then i want to expect that is to have text content so specifically that's going to give us a dom element and then we want to make sure that that text content is the string hello world now i've got some linter errors right now if i run my linter it inserts the the indentation and everything that i wanted but this is my my basic test i'm going to render the app and then select the h1 and then make sure that that h1 has hello world inside of it you can see in this case we didn't really do any acting but act would come into play if you need to click a button or fill out an input or something like that so now we need to run our tests let's set it up in our package.json so if you go to package.json we can add a script here called test and that specifically we'll just call v test so now when we run npm test it's going to call v-test v-test will search everywhere for any file that has the word test inside of it and it will run those specific tests so at this point let's run the test so if i do npm test see what happens oh no a failing test so if you remember earlier we actually we didn't have a hello world anymore now we just have that input so this test is failing for a good reason it got the wrong output like there wasn't there was no h1 on the page so let's fix that i'm just for now i'm just going to completely delete this form add ourselves an h1 and then put the text hello world inside of there we can run our linter we'll do that now by default v test watches for changes um and uh then we'll rerun the test but you can see we're a bit closer uh so right now we expected the element to have hello world but we got back hello world so i forgot to capitalize the w that is a thing yeah people are telling me in the chat it's gonna fail again and nice we have uh one one uh one passing test so that's awesome so we're set up for at least a basic app tests later on when we have uh things like http requests we're going to want to do some other setup but this is good enough setup for now what i want to do is take a quick moment to talk about how you should select your elements and where to find good resources on that so if you look in the testing library documentation they actually have a ton of opinions and a ton of guidance on how you should write your tests and like what you should use to select elements uh they have this uh page called uh priority of selecting and they tell you that when you're selecting elements in your tests you should go down this list and start at the top so you should try to find a way to select the element by roll and what that actually is giving you is accessibility testing along with component testing so if you select by role not only are we testing that we could find the element we're also attesting that this page has a heading element that is level one and that's an accessible thing uh in terms of accessibility every page should have an h1 so by using that selector you're getting accessibility testing and component testing all in one go and this page basically says if you can use get by role if if you can't figure out a role for it then do maybe label text placeholder text basically go down this line starting at the top um because these the ones at the top are the more preferred ones um there's also a really good article written by kinsey dodds the creator of testing library that lists common mistakes with react testing library and they specifically have the they talk about the get by role right here uh so this says um if you're getting by test id so this is a pattern you might see in some in some code bases where uh developers put test ids all over their elements and such so that way when you're writing tests you can select that one specific element but again that's that's not testing accessibility and it's not testing how a user would inter interact with the page whereas if you test this way you're testing how a user would technically interact with the page i am by no means an expert in accessibility i just know there are certain things that you should do that are going to help with screen readers and and people using the accessible features of your website i've seen some apps and some teams that use test ids and the scenario that i saw it in it was the testers were actually separate from the developers and the testers were always like hey i need a test id for this element because i can't figure out another way to to select it so that's one way of going about it but specifically testing library is telling you that's not a good practice to follow because you should be testing your components in the way that a user interacts with the page now let's set up react router so by default our react app is super basic right now it just has a single component that just says hello world we don't really have a way of having multiple pages so we're going to set that up with react router now there are some other options for react router and we're at a point in time here in 2022 where there are some other things that are gaining in popularity but react router was and is one of the most popular for a very long time so we're going to set this up but just know there are other ones they work similarly we're going to go with react router so first off we need to install it we're just going to do an npm install of react router dom and we are using react router dom version 6. cool so we have that as a dependency and now we can set things up so if we go over to our app.tsx one of the things i like to do is i actually like to export my app that has all of the things wrapped around it so specifically you can see whenever we set up uh react router we wrap our app with that router so i'm actually going to create a function called wrapped app and this in turn will have the uh in my case i'm going to use the hash router from react router dom so it'll have that and then it will have the app inside of it and that is going to be the thing that i export by default instead of app so this would be good for two things for for testing we typically want to test our app um that has all of the other stuff in it so routing and eventually if we set up context that'll need to be here or anything else we need to wrap our app in we would need to test against that so it's it's easier to test against it if i'm just exporting that thing standalone with it wrapped now we might actually create a separate version of app that is only wrapped with the things we need based on the tests that were that we're running but for now this makes sense to me and so i specifically am bringing in hash router browser router is another option but browser browser browser router uses the history api and state to manage the different pages that you're on but the issue with that is if you deploy this react app to a static file server you usually will have to configure it to allow 404 redirects to the index i don't want to have to do that so we're going to use hash router because i can deploy this to any static cdn i don't have to do any custom configuration and my my front end routes will still work people complain that the the hash in the url is ugly but uh it allows me to like i said deploy to any cdn don't have to worry about uh redirect configuration or anything like that okay now that we have exported the wrapped app um we should be good to go here because now the main.tsx is still importing app but in this case it's getting the wrapped app because that is the uh default export um over here i am just going to run my linter because it was things things have changed since so now that we are using the hash router we can actually set up our routes so for that we specifically need the routes component and the route component so routes wraps all of the route components that i'm setting up so i can import both of those from hash routers so now we're going to make our app a little more complicated i'm going to wrap it in a div and it'll say still say hello world for now so that our tests still pass and then i need the routes component you can see that that will import from react router dom we'll do like that and then i need the route component which also gets imported from react router dom like that a route has a specific path so in this case i want a path at slash so this is where i'm going to load my homepage and then i can specify an element that should load so at this point point i need a home component um so what i'm going to do is here here in my source directory i'm going to create a folder called pages and these this folder is going to hold all of the components that are top level now there's been a lot of different ways of doing this in the react world sometimes this is called containers sometimes it's called views i'm going to call it pages they all sort of mean the same thing it's essentially the top level component that loads other components so i'm going to create a component here called tsx we'll have a function home this one actually will just render the h1 uh hello world so we can remove that from our app component and then i'll export this default so now we have a basic home page over here in app.tsx i'm going to import that home component so pull it in from pages slash home great now we can get rid of this hello world and then right here i can say element and i specify that to be an instance of the home component so now when the page loads when the route is slash it will load the home component if i run my tests they should they should work because we still technically have an h1 on the page after it renders awesome test pass but uh let's also add like a not found page and then we'll write a test to make sure that that is working as well i'm actually i am going to get rid of these top level divs i do just want my routes at the top level like that and the test should still pass because i haven't i wasn't testing the structure i was testing the the contents and so the contents are still there great um so at this point let me add a let's let's add just a not found page and it's going to be pretty basic similar to hello world but instead of saying hello world it will say not found we're going to call this not found and then i'll add this as well great and so now we need a route that whenever none of the other routes match we show not found instead so we'll create a route in this case we'll set the path as star so if none of the other routes match then we're going to load this specific component and so here i'll do element equals and then we want our are not found like this cool so now if i go to a page that uh we didn't specify in this case we've only specified the home page um we will uh see this not found page so now let's test it out um and so in the browser here um if i want to go to these routes because i'm using hash router i always need to do slash hash and then the specific thing that i'm looking for so in this case let's try to go to the banana route which doesn't exist and then our not found route gets loaded which is great um so let's actually add a link on this page that goes back to the home page and we can see another feature of uh react router so here in not found let's add a link we'll just do a little react fragment here get rid of that and then right here we'll add a link so link gets imported from react router dom so we'll have a link and then inside of that link i'll just say like go home and then we say this link wants to link to and in this case i'm just going to link to the slash route and so link is provided by react router dom if i run my linter it'll remove those double quotes but it's provided by react router dom and so now when i click on this it specifically is going to use hash routing and it's going to take me there to home so if i save that now we have this link and if i click that you can see we get back to the hello world route so now that we have this not found route and we made sure that it works let's actually write a test to test it so over here in my app.test i'm going to add another test underneath this one and i'll say it renders not found if invalid path and now we have to do things specific that actually have to do with uh react router so if you look on the testing library website go to examples they have a section on react router specifically react router version 6 which is what we're using here and they show you how you can set things up so they have some example code which sets up a router and then in their tests they use this thing called a memory router so one of the things we need to be able to do in order to test this not found route is we need to be able to essentially render our app and then like navigate to a specific path the way we can do that is with memory router because we can give it array an array of paths that to load and if we give it a path that would load not found that would actually uh feed down into the app that gets rendered and then our not found route would get rendered so memory router is another thing provided by react router dom you can see that we get a browser router and hash router which we're using but we also get memory router so that's what we want to use so right now in our render we specifically want to use this memory router from react router dom and then we want to load our app inside of here we're going to need to fix this in a second i'll show you that but we can provide initial entries and in this case it's an array and we're just going to do like slash banana so we know that this should load the not found route because there is no path for or there is no route for slash banana all right let's fix our exports so in our in our test before we were actually testing our wrapped app so you can see um right here we imported app but if we look at app.tsx we have our wrapped app as the default export so that's the one that has the hash router on it and as we add other libraries and such it's going to have more things wrapping that app that's not the one that we want to wrap with memory router we want to wrap this standalone with remember with memory router so i'm also going to export uh specifically app and now we can import these uh separately and actually i'm going to go ahead and remove the default export so that way when i'm importing i can specifically choose which one of these i want to import do i want to import wrapped app or do i want to import app over here we can now bring in both of those i can bring in the wrapped app and then i can bring in the app our initial test was for the wrapped app like that and then this test is for the non-wrapped app uh this is a linter uh thing that's that's complaining about my um my order of imports you may have never seen this rule before but i really like it essentially all of the imports that are coming from your node modules go at the top of your file and then anything you're importing that's files you wrote go below that so i wonder if yeah eslint can fix that it basically is like oh put that above the other one i usually like to group them like that as well okay so we've handled that there um this will actually result in a failing test but let's see it fail and then we'll run this um and specifically we want uh and actually so let's test this for a failing test first so let's just load the home page um and then we want to do a similar expectation that we had before but in this case we want to expect that we see not found but this should fail for multiple reasons it's going to fail because i'm loading the slash route which actually should road hello world not found and then also our main.tsx is broken because um we changed the way that this was exporting although i don't know if our tests are going to pick that up let's see let's see let's do npm test cool so yeah we expected it to not have not found but it had hello world um that is because we need to pass in a not found route so right here like this route does not exist and because we're starting up the app with that router it should load the not found route so if i save that we now have two passing tests great so that actually didn't didn't bring up the error i was thinking of i think if we try to run the app we should run into an error let's see yes ambiguous indirect export um basically we're exporting two things now app and wrapped out we don't have a default export so over here in main.tsx we need to fix that we need to specifically import the wrapped app and then we'll use that wrapped app right there and then we get our hello world so at this point if you saw me talking about unit tests you might be thinking hey this isn't a unit test because we're basically testing the react router library and you might be right i just wanted to show some tests here and in the meantime if we if we were to go in and update this code and for whatever reason get rid of this we would now have a failing test that we don't have a not found route and so that gives a little bit of benefit to this test basically this test makes sure that in the future if we accidentally remove that catch-all or or something else we still we have that test which is uh capturing that functionality however uh what we're writing right now with unit r what we're writing right now are unit tests uh if you look at veet veet is a unit testing library so we're testing individual units we're not testing the system as a whole and one of the people in the chat nfgcodex made a good argument that was right now we are actually testing react router like we're making sure that rat react router works versus making sure that our app works and that's more of an integration test because we're integrating with that library versus a unit test which is testing one individual component in this case we probably would have unit tests for each individual component like have a unit test for home have a unit test for not found instead of a test that is tracking to see and make making sure which which page gets loaded um in in this scenario though i will say there are some good use cases for testing when the path changes does the right thing load because if we're testing the interaction of a page and interaction of a component uh it might be that when a user action is done they get redirected to the home page um and so we might want to check against that and so we might have a test similar to this so that's all i have to say about that as we write more tests in our in our example apps um we'll make sure that we're testing the unit only and we might use this example later if we are testing react router specific things so that's all for this setup video um hopefully it was useful to you uh either you're following the setup along with me or uh you can uh clone this setup that i created from from github so github.com codingguard and slash react ts starter it has all of the all of the the base code that we've written today so if you're starting a react app and you need these specific dependencies you can get up and going from there but thank you for watching and we'll see you in the next one [Music] you
Info
Channel: Coding Garden
Views: 78,331
Rating: undefined out of 5
Keywords: javascript, coding, programming, node.js, tutorial, learning, debugging, web development, web, full stack, backend, frontend, live stream, live coding, vite, vitest, typescript, eslint, prettier, airbnb config, setup, react setup, developer tooling, compilerSettings project, tsconfig.json, eslintrc, vitest jest-dom
Id: cchqeWY0Nak
Channel Id: undefined
Length: 54min 23sec (3263 seconds)
Published: Fri Sep 02 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.