Five Clever Hacks for React-Query and SWR

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so you thought react query and swr were just about fetching data turns out i've got five different ideas for you about how to reuse swr or react query in new and novel ways let's get right into it one of the things that i love doing on this channel is getting you to think differently about the things that we use on a daily basis for example the awesome data fetching libraries of react query and swr now of course you can use these libraries to make atomic requests to a server but you can also do some really cool things with them and that's i'm going to show you in this i'm going to show you some examples and get you thinking about different ways that you can use these awesome libraries and be sure to stick around until the end because number five will answer the age-old question about whether or not if you have a data fetching library like react query or swr do you still need a state manager we'll find out but before we get into that i did want to give a heartfelt thanks to everyone who has commented in the blog section of the youtube channel my wife is in the hospital with acute leukemia she is getting better which is great and i just want to thank you all so much for all of the heartfelt outpouring of good thoughts and prayers it was just it's just really wonderful now a lot of you asked if there are things that you can do for me and us and i think that's great the best thing you can do is just donate blood and we would really appreciate that and i'm sure lots of other patients would as well all right let's jump right into the code so in the description down below you're going to find a link to the github repo that has all of the code that i'm going to show you in here and there's basically two different versions of the same project now i already have the swr version already done what we're going to do together is create the react query version and then kind of reference the two to show what like small differences there are in the implementation of these two things but it's pretty cool stuff so the first thing we need to do is basically set up the react query version of this by the way there's also an article that is associated with this video that's also linked to in the description down below so let's go with this setup first i'm going to do yarn create react app and i'm going to create the rq version okay it looks like we're all good now i'm going to go into that rq version directory and within that i am going to add our ui library which in this case is mantine so i'm going to add mantine core and mantine hooks and i'm also going to add react query okay looking pretty good so let's go and drill into our app.js and i'm going to remove a lot of stuff since we don't need it back door remove all of that and what i'm going to bring in from mantine is the container as well as stack which is a vertical layout manager and then also title which is just like an h2 sort of thing or h whatever you want so make a stack and then within that i'm going to put the title of our first example which is going to be a login example and i also want to go and set up react query so what i'm going to need to do is kind of wrap this in a query client provider so let's go make that client first so i'll make a file called client.js and i'm going to import the query client from react query this is not something you need to do with swr so it is and then we're going to export the default which is just a new query client all right now we've got our client so i want to bring that into our app.js and now down here we're going to have our wrapped app and that's going to wrap our app in the query client provider so let's go and bring that in query client provider and we'll bring that in from react query and now down here we'll have a wrapped app which is just going to be our app but wrapped in that query client provider and i'll export that as the default and let's see let's give it a try so we'll do yarn start here and see if we got a good working app hey looks good okay so we got our login up there and that corresponds to the title right there so here's what we got example number one it is a multi-stage request so let's imagine that you are writing like the auth slash get the user data flow for an application and the microservices stack that you're talking to the first thing you need to do is make a request to log in and that's going to give you back a user id and then with that user id you can request again the user information like the name all that now ideally you would get that all in one request but the microservices folks are like no it's microservices we don't want to do that so you have to make two requests so you're like oh man okay fine so let's go and kind of mock this up by creating some example data over here in public now the first thing i'm going to make is like like a login.json and it's going to have the ide that's coming back the idea would say like 2200. 2200. now we got to go with that id and go make a subsequent request and get the data for like user 2200 so let's have 2200.json and it's going to have you know some data in there you know first name is jack last name is like sparrow argh okay so here's the idea right we need to make one fetch it's going to get that id back and then we're going to make a subsequent fetch once that's completed to go get the 2200 the user data because that's what we really want to put we really want to put that on the screen so okay let's go over and create our code for this so i'll create a new file and call it login.jsx and the first thing i'm going to do is create a component so we're going to have the login component and we'll just return at some point we're going to return some text here and that text is going to have some data so a moment we'll just json stringify null into there and we'll bring in that text from mantine and then we'll export this as the default all right now let's go over to our app and we'll bring this in so import login from login and we'll put it under login now it should just say null there right now and it does cool awesome okay so now we've got a working page now we need to start making our fetches so the first thing we need to do is bring in use query from react query and we're gonna go make that login fetch so we'll do that we'll have data is gonna be the login data and we're gonna call use query and it's gonna have a key of login and then we need to go fetch that so i'm going to make a function we'll call it fetch login and we'll just put it in there and call it and this is going to be defined up here fetch login just going to do fetch we'll just say login.json and then we will get back the data by getting the response back and getting the json out of the response okay cool and let's uh let's stringify that in there and see how we go okay cool we got our id 2200 right so this is the thinking right now that i have one fetch and i'm gonna have one hook per my one fetch so what i need to do if i want to continue on well i would need to go and make the user id fetch so i'm gonna have fetch user and it's gonna have an id and then we're going to use string template and we're going to say that we're going to put the id in there so it's going to give us our 2200 right and now we got to go get that data so we're going to say we'll fetch the user and call this data user but we need to give it that id so where do we get that from well it's going to be login.id but we don't know if it's there yet it might not be there so what we should do is use a question mark dot basically say well if the login is null then don't blow up but we don't even want to run this until we have that data so we're going to use the enabled option on here to basically say well only do this if the login id is not undefined cool right so hit go and yep that worked so we actually got the login and then we use the login to do that fetch and yeah this works but it's kind of a pain and imagine if you had like three or four of these requests you know it's going to kind of stack up the complexity is going to get out of hand so what's an easier way to do this well an easy way to do this is to do what i think a lot of people sort of don't think about when they think about how to use things like react query and swr and that's to actually make a function that is an async function and use that to as your source of your promise that use query or use swr is going to monitor so let's do this let's go and make a login function and it's going to be an async function so that we can use a weight and all that and what we're going to do is we're going to get our login response by calling await of the fetch login clean enough and then we are going to return and await for the fetch user with the id that comes back from that login response now we can go and replace fetch login down here with login get rid of all that and this is going to be our user data and bob is your uncle so now this login can be as complicated as you want it can have multiple requests you can have try catch blocks you can have all kinds of error handling all kinds of logic in here and you can still use use query or use swr in this context in fact the article that goes along with this video which is pointed to in the description down below has a bunch of different variants of this for example sequential fetching parallel fetching using promise.all so some nice examples for you to work off when it comes to handling multiple requests from a single use query so how does this look like in swr that's a great question let's go take a look so the swr variant is not all that much different so go back over here to the swr version and take a look at login.js and we've got our fetch login just like before fetch user just like before same exact login function the only difference in this case is that instead of use query from react query we're using swr and use swr and that's it so really nice actually one of the really nice things about swr in this case is you don't even need a client you don't need the query client provider at all the app.js is just the app there's no wrapper or anything like that so you don't need that top-level query client provider when it comes to the app.js all right so the next one we're going to do is a stopwatch example we're going to turn react query into a stopwatch how cool is that because i know you're like hey wait a second you said this wasn't this video wasn't about fetching but all you've done is fetching so far let's not do any fetching let's go and make a stopwatch using react query so how do we do that well let's go back over here to our app.js file and then i'm going to go and add a title for stopwatch and let's go create our stopwatch example so i will do stopwatch.jsx and i'm going to go and create a component called stopwatch and it too will have a piece of text that says the time and then it's going to have some number in there right number of seconds past when the component mounts so that's going to give us our stopwatch and then i'm going to export that as the default and now we need to bring in that text from man time and let's go bring it over under our app and we'll take a look at it and there you go so times zero obviously it's not going anywhere so how are we gonna make a stopwatch well there's two parts to a stopwatch right there is knowing your starting point so knowing when you clicked that button and got that stopwatch going and then there's actually looking it at it every second to watch it kind of go so we're gonna break this problem into two pieces the first piece is figuring out when we started and the time elapsed since when we started so what we're going to do is we are going to create a functor that's a function that creates functions and we're going to call it create stopwatch and what it's going to do is it's going to get the starting time by calling date.now which is just a number and then it's going to return a function and every time you call that function that function is going to give you the time in seconds from between those two things so between the current time and when it started so we're going to turn [Music] math.round from datetime now minus the start time over 1000 because all of this is in milliseconds and we want it to be in seconds so now we have to create our stopwatch in our component so the way that i'm going to track that is i'm going to use it use a reference for that so i'm going to call use ref from react and we're going to get our timer ref and that's going to be a use ref where we just call that create stopwatch so timer ref.current is our function and every time we call that function we get the delta between when it started and now so how do we do that well let's bring in our good old friend use query from react query and we're going to get our data which is our time and we're going to use use query and we're going to call that function timer ref current now if you're like whoa wait a second jack this is not an asynchronous function this is a synchronous function it doesn't matter it's really cool it can call either it actually doesn't care whether it's a synchronous function or an asynchronous function so let's do that let's do time in there and see what happens so we'll hit start and we get zero so there's zero delta between the first time that it created that stopwatch function and the first time the usequery actually pulled that function so we can do is we can say that we want a refetch interval and we can set it to say i don't know 100 milliseconds go and check every 100 milliseconds to see if there's a new time let's hit save and there you go we have a stopwatch how cool is that neat right all it's doing is it's basically reusing the mechanics that are already built into use query which you might have thought hey that's when we go off and we pull a service over and over and over again well you don't have to just pull a service in this case you can pull whatever you want like a stopwatch function all right so you want to see how this is done in swr let's go have a look so i'm going to jump back over here to our swr version and take a look at the swr version of our stopwatch exactly the same create stopwatch functor exactly the same stopwatch ref and then down here with our use swr instead of doing refetch interval we do refresh interval and deduping interval so two instead of one but hey very little difference in the implementation between these two things okay but i know you're saying to yourself i'm not going to go and build a timer with react query that's just nuts and i i kind of agree honestly so i'm going to give us a more practical example and call that our our second example and but it's going to be based on this timer example so here's the problem we have a service which is logging data to us and it is logging data to us at a high velocity let's say that messages are incoming at say every 100 milliseconds at 200 milliseconds but the user the customer really doesn't care about this log and they don't want to see it updated that often maybe they want to see it updated only every second or every couple of seconds because it's just not that important they got to see it but they don't care that much so how do we go and use something like react query to do that throttling for us well i'm going to start by creating a file called logger.js and i'm going to export a new component called logger and logger is going to have like a stack of log messages so we'll do a stack and then within that stack we're going to have some text items but we'll just keep it at the stack at the moment and we'll export this as the default and then we'll bring in stack and text from mantine core and let's get this going so i'll go over here to the app and then i'll bring in logger and i'll add it down here as logger cool let's take a look there we go logger so now we need to go and make a a simulated log so i'll create a new function called subscribe to log and it's also going to be a functor and it's going to return a function that when you call it gives you the most recent contents of the log so we're going to start with an array which is all the log messages and then we're going to have an index of the current log message and start at zero and we're going to have a set interval so we're going to have an interval that basically just simulates this incoming log so i'll say set interval and it's going to be a function and that's going to get called every 100 milliseconds or so and then every 100 milliseconds we're going to push in a new message i'm going to say log.push and it'll push in a log index and we'll say also the date dot now right just the current time and it'll bump that log index but we don't want this kind of overflowing the screen so i'm just going to limit this down to the last three log messages so say log dot slice just take the last three that's going to basically pull off the last one and just keep the list at like three or so and then we're going to return a function which gives us back the log current contents log so now we've got our subscriber now we need to go actually subscribe to it so we'll create a log listener that's just going to subscribe to that log and this is what we're going to pull using react query so we'll bring in again use query from react query and then we'll have our data which in this case is gonna be the log and it's gonna go against that log listener right so what do we do with that log well we need to go map through it so let's do log.map and then we'll go and just print it all out there all right so let's try it let's hit go and we got an error let's go take a look and see what the error is oh there's nothing okay there's no data yet so let's do question mark down okay cool all right there you go well it shows some log entry there just for a second i think that was like a hot reload sort of thing so what's happening right now is it's actually running we're not actually doing that re-fetch interval so that's this is when we bring in the refetch interval and this is when we get to actually throttle how fast we want it so in this case let's go with a hundred milliseconds first and see what happens so you can see that this is really really fast moving it's like dun dun dun dun dun dun dun dun dun go go go go go go go go go and usually whoa i don't want to see this much log i don't want to see it go that quickly so i'm going to go and tweak this to say every second there you go now i've got a throttle how cool is that that's really nice i like it all right so let's go take a look at the swr version of this so go back over to our swr variant and dig in there and our swr variant of logger is exactly the same thing except that we are using refresh interval as opposed to refetch interval and we need to put in this deduping interval to make sure that it actually makes the request every time all right so what's up next well let's take a look so what's up next is a gps example we are going to use react query to make a gps request how cool is that from the browser itself let's go check it out so i'm going to go back over here into rq version and we'll go bring in a title for gps and then i will go create a file called gps.jsx and the first thing i'm going to do is create a component called gps and it's going to return some text that's going to have our coordinates in it and i'll export that as the default of course i've got to bring in text from the mantine core and now before you go actually let me bring in a big piece of code here this is a get gps coordinate so what this does is it gives us back a promise when we call it it calls the get current position function which is kind of an old-school callback system it basically gives you your current latitude and longitude so we're just going to resolve the latitude and longitude and if we get an error then we'll reject it with an error this is basically wrapping this geolocation getcurrent position in a promise all right let's go back over to our app and bring in gps and we'll put it down here all right let's see do we have a gps yeah we do cool now we need to actually go get the data so how are we going to do that well i'm going to use use query for that from react query and we'll say that we have our incoming data and we'll use use query with a key of gps and that function to get the gps coordinates which was return on promise use query is going to manage that promise for us and once that promise gets resolved then we have our data so let's json stringify that and now we have our latitude and longitude by the way if you want this to show any arbitrary position you can actually go over into the inspector and then bring up the sensors by doing shift command p and then sensors and you do show sensors that goes down here and then you can override that location to anywhere you want like mountain view for example now now it's a mountain view ta-da pretty cool huh okay so how do we do this over in swr let's give it a try so go over here to our swr version and as you can imagine it's almost exactly the same thing the only difference is use swr versus use query now the next one is actually something that i've seen used in applications that i've worked on and i've worked use this myself when you want to build an application that's multi-threaded you use web workers now to talk to a web worker you have to go and send back and forth messages and it can be kind of painful but actually react query and swr make it really easy now we're not going to be able to do this with what i have right now so what i need to do is i need to go and stop the application and then i'm going to add in a webpack extension that's going to allow me to really quickly add web workers to my app and that extension is called the workerize loader so let's restart now that i've got that going looks pretty good so now let's go and create a web worker i'm going to go create something really simple create a file called worker.js and in it we're going to have a an exported function called multiply numbers it's going to take two numbers and return the result of multiplying those two numbers together thus multiply numbers obviously you're going to want to do something more complicated than this but this is just really for demo sake so let's go and create a webworker.jsx file and now i'm going to import that worker using that workerized loader so now i've got the worker i need to go and create an instance of that worker and now i need to create a function and we'll call multiply numbers and what multiply numbers does is it adds an event listener to that instance basically saying wait when you get a message back from it then here's what i want you to do i want you to resolve the promise with the result that you get back so this is the result of the post message over here and it looks to see make sure that the message coming back is a result and then it does the worker instance multiply numbers with the incoming argument so give it an object that object would have a and b in it and then it would go and run that multiply numbers okay so now we've got to go and create our components so we'll call that webworker and this one i want kind of two text boxes and then the result kind of laid out horizontally so for that i'm going to use a group group does a horizontal layout and stack does a vertical layout so i'm going to bring in group from mantine core as well as text input a button and also text so we're going to have two text inputs two of the two different values a and b and then a button to say do the multiply and then some text to display the resultant value all right so let's go build our text fields first so i'm going to use use state for that and down in here we're going to have our two use states for our value a and value b then we're going to have our text inputs for value a and value b that set those values now okay sounds like a good time to actually go and export the default here and then bring it into our app so go back over to app.jsx and we will import webworker and then make a title for webworker and drop it in there let's take a look okay cool so now we've got our two text fields 10 and 20 down here pretty good now i want a button and also the piece of text so now is when we actually start to hook it up to our react query so we're not really doing a query here we're kind of doing more in my mind of a mutation so in this case i'm going to use use mutation from react query because we're essentially doing an action kind of calling something calling a function and so i'm going to categorize that as more of a mutation so down here i'm going to say that the data is let's see the value i guess coming back and then we're gonna get mutate from use mutation which also takes a key first so we'll call that multiply numbers and then we'll give it that function multiply numbers cool okay so we'll put the value down here and a piece of text and now we just got to make that button so we'll create a button we'll say that it's multiply and then here on click we're just going to mutate and then we'll give it the two values so in this case you know i'm just going to make it like plus value a and plus value b thanks for thanks github co-pilot but i'm it was a bit much so the plus automatically will coerce it into a number okay let's give it a try let 10 20 hit multiply and get 200. awesome hit 5000 here by 5 and you get 25 000. so isn't this a really nice way to be able to communicate with a web worker right so all you got to do is just kind of wrap it in something that promisifies it and then you can use use mutation to run your web worker how cool is that okay now there actually is this one's a bit different when it comes to react query versus swr because swr doesn't have a mutation in it doesn't have to use a mutation so how does this work well okay so the implementation here is slightly different so you have used swr and you give it a key that key is multiply and then we're going to give it this odd kind of initial function so this initial function is just going to return the initial data for this we'll just set it to 0 to start and it's going to hold that result but it's also going to give us back this mutate function now this mutated function is kind of interesting what mutate allows you to do is a little bit unexpected mutate takes a new value and then just mutates the local cache and if you don't revalidate then it actually won't go and re-get data but if you don't pass revalidate what you're basically just mutating the local cache temporarily until you get back the result from the server so we're doing in this case is we're manually calling multiply numbers ourselves and then as a promise we're waiting to see that when that resolves and then once that resolves we are then mutating our local value for swr for that result here and that's how we use used w use swr to actually hold the state of the result from this web worker it's actually kind of almost getting around swr entirely in this case i don't think i actually use swr but i think there's you know still it's interesting to see the different approaches here the lack of a mutation function in swr is is pretty interesting and it's a big difference between react query and swr and it's something that actually starts as a good segue into our fifth and final example which is super exciting because it asks and answers that age-old question of do you need a state manager if you already have react query or swr and the answer is well you probably do in any real world in any large application you probably have one already but in the case of small applications maybe you don't because you actually can use react query or swr as a place to hold global state which is kind of like 80 percent of what a state manager is doing i mean the other part of a state manager is obviously all of the process around changing state like if you have x state and you're using a finite state machine or something like that i mean there's obviously a lot of rigmarole around that but i think you know holding state as globals is large a large part of what a state manager does for us so so let's go build a react query state manager all right we're going to go over into our app.js and i'm going to create a new title we'll call this one global state and we'll create a new file called globalstate.jsx and let's bring in some prereqs so i'm going to bring in text and text input and stack just like we had before from mantine core i'm going to bring in use query and then bring in the query client and that's actually kind of important in this case now we're going to have three components in here so we're going to have the global state component and that's going to have a stack and in that stack we're going to have two components the first one is the state editor and the next one is the state viewer all right now let's export this okay now what does our state editor look like so we'll have a state editor and it's going to have a text input in it and so what we'll do is we'll say that the value is a use query and we'll call this shared text and the function in this case is just going to turn an empty string so it's going to start off this is the initial data and this initial data is going to be an empty string and we're going to say that it is not enabled and so in this case the text input value is going to be that value and the cool thing is the state viewer is basically going to be the exact same thing so we'll do state viewer in this case it's going to have text and that text is going to have in there okay so let's go and hook this up to the app and see what this is going to look like so over here we'll go and bring in global state and then i'll go down here and add it as a component let's take a look so now we've got this text input field down here and the idea is when i type in here that it should show up down in here because these two are going to be essentially linked they're going to show the same piece of data so what i need to do is somehow magically teleport this value from the text input to this value down here it which is in our state viewer so i'm going to do that okay so how am i going to do that well what i can do is i can look at the on change and the on change is going to give us an event and what i need to do is with a client i am going to set the query data then i give it that key the shared text key and then give it the current value so let's hit refresh and see what happens all right looking pretty good now can i type in there oh my gosh wow so what's actually happening here so what's actually happening is we're using the cache of the query client in this case to hold that piece of data that shared text value now we can actually make this a little bit more generic for example we can go and say that we have a use rq global state hook and so what does this need to have well it needs to have the key right and the initial data and then with that it's going to return a an array so we're going to model this like use date it's going to have the first value is going to be the data and the second value is going to be a setter it's going to set that data so let's see we'll bring in this piece of code right here so use query and from that we're going to get data so that's going to be our data value and let's see we can do a little bit better here we can set that to the initial data we can set initial data down there cool and then down here for the setter we'll take the value and then we'll do the client set query data and then give it the key as well as the new value cool right okay so let's try this out so we're going to go and replace this guy so we'll have value in set value and we'll say it's going to be shared text we'll just start it off with nothing get rid of this have set value here replace the set value there with the ebt target value nice come down here all you have to do is make sure that we have the same key in both places we don't need the set value since we're only reading it in this case and let's try it again very cool now we have a generic hook that actually uses the cache that you already have if you have react query to store data now would i do this with real business data no probably not in a large application you're probably going to already have a global state manager and you don't need to do something like this but if it's a small application and what you're trying to just share around between components is something say like a user id and a jot this actually might not be a bad way to go you've already got it there and either you could use this or use context but i don't know if you really want to bring in a full state manager for just that and i think this is actually i don't know pretty interesting is a way to go certainly an interesting option for you the swr variant is i would say relatively you know maybe even a little bit cleaner so we'll go take a look over there at global state and this is our use swr global state hook so it has exactly that same api surface is gonna give you back the data and the and a setter just like you state in this case we have that initial data we have that key we're going to give you either the data or the initial key and then we're going to use that mutate function like we did in the last example with that revalidate false to set that cache value in swr and use the swr cache again as our global state manager of assort pretty cool all right well i hope this video gets your juices flowing in your mind thinking about all of the things that you can do with react query and swr and take advantage of these awesome tools i can't wait to hear what you do with it of course all of the code is available to you in github for free and the link down below as well as a cool article that goes into more depth on this in the meantime of course if you like this video hit that like button and if you really like the video hit the subscribe button and click on that bell and be notified the next time a new blue collar coder comes out
Info
Channel: Jack Herrington
Views: 49,842
Rating: undefined out of 5
Keywords: react query, SWR, react swr, blue collar coder, jack herrington react query, react query and swr, React Query, react query tutorial, swr react hook, swr react, Complex Queries, Web Workers, Global State, react query global state, react query web workers, swr global state, swr complex queries, swr setup, react query setup, react query swr, swr react query
Id: JaM2rExmmqs
Channel Id: undefined
Length: 40min 9sec (2409 seconds)
Published: Tue Jul 05 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.