🟣 How to simplify your data fetching life with RTK Query

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
foreign [Music] toberfest 2022 my name is Michelle moudy I am a developer advocate here at sap I specialize in front-end development and popular front-end Frameworks and their connection with sap Technologies today I'm going to be talking to you about rtk query this is built in with Redux toolkit and is a way to simplify how you fetch data on the front end I'll talk to you today about what rtk query is why you would use it when things like Fetch and axios already exist how you would use it in actual code and what else you can do with rtk query so the link to the repo that you see on screen this UI react Redux samples is where all the code is currently being hosted if you want to follow along and code with me you're going to want to switch to the data fetching main branch as that is where I am starting from as well it has all the code in the main branch but with Redux toolkit added to it as a good starting point here I would also recommend installing the Redux Deb tools extension for Chrome and Firefox if you haven't installed that already this is because it will allow you to get a better idea on what's Happening to your store as we go and mutate the state along with what queries are being called and when so what is rtk query it's an incredibly powerful tool built into redox toolkit which is where the rtk comes from that helps improve and simplify how we fetch data on the front end it can do the same things as Fetch and axios written in a much more elegant way in my opinion along with a lot more complex things with very few lines of extra code one of the examples that I'll show you later which is the one that I was most excited about when learning about rtk query is the ability to with one option and one number repeatedly query an end point which can help in a number of use cases another really neat thing that I learned when creating this presentation was that you can fetch in multiple different places and when you fetch in one place it'll update in the other place as well so you don't need to track if some data is getting updated and then immediately update it in the other place or put it into the state you can also very easily invalidate the data you have in the front end when you make a call to update the server which is fantastic because you don't want to have out-of-date data on the front end there are many more fantastic ways that rtk query can help benefit us and I'll go through those a little bit later in the presentation for now let's jump right into the code here's what the running application currently looks like and I want to be clear here I'm only really going to focus on where the API calls are made so I'm going to leave out a lot of the functionality we have two tabs personal information and messages that work we also have this notification Bell down here which has a list of notifications the count of unread notifications and when you click off of it and back you'll notice the number went away and when you click back on they won't be bolted anymore we also have these star icons here which are clickable it doesn't look like they do anything yet but they actually are making calls to the back end we just can't see them on the front end very easily if we were to switch to personal information and back to messages we would see that these are starred now because every time we switch we make the API call to get the messages again and every time we get messages we set our notification list to add the messages that we haven't seen yet and this will all be more clear as we code along so there are a couple problems with the application as it's currently implemented and I want to be clear that these could be solved without rtk query it's just so easy to do with rtk query I wanted to demonstrate that so the current problems are the first one is obviously when we click these we don't see an update on the front end we have to switch to personal information and back to messages to see that update the other thing is every time we switch tabs we make another API call even if messages isn't even on the screen which is not exactly the behavior we want another thing the only time the notifications list ever actually updates is when that API call is made so when we switch tabs typically the behavior you want for notifications is for those to pop up and update periodically over time regardless of what's on screen we don't want to have out-of-date data in that notifications list until we switch tabs or the user does some kind of action because it could be a really long time before that happens we want to be able to set the interval that that notification list is updated so we will start solving these problems by adding our rtk query API and adding our first endpoint the simple get call that grabs all of our messages we will put them in the exact same place as they are now and then we will start to expand that by changing how and when we call that API then we'll update our notification list and I'll show you how to repeatedly query the same endpoint which will update our data in multiple different places which is very exciting from there we'll add our second and last endpoint a put call and I'll show you how you can expand that so that every time we call that endpoint we make sure that the front end is updated this way the front end is always dealing with the most up-to-date data as we know it so let's start by learning how to run the application the first step after pulling a new repo should always be to run a yarn install mine are already up to date yours might not be so just make sure to run that and wait for it to finish before you move on to the next step the next thing we need to do is run yarn server this is because we are making API call so we needed a back end and I used Json server and node mod to create a mock back end for us to use now we need to actually run the application itself and I'll do that by just running yarn start if you ever forget these commands or want to know more about which ones are available you can always look at package.json this will show you all of the scripts that we have and is a good reminder if you've forgotten which I do frequently as I said before the first thing that we're going to do is we're going to set up our API and our first get call so the first file we want to look at is app.js that is because this is the file that holds our get messages fetch along with the main content for both personal information and messages and if you'll notice here I've actually set this up to use fetch but we'll be replacing that with the rtk query API which is our first step so to do that I need to create a new file in this API folder that I've already created and I'm going to call it messages API please note I will be copy and pasting a lot of code that's just to save myself time but I will point out the important bits of the code as I go along so let me go ahead and grab the first part of the code that we need for the API so to get started we are using the create API function from rtk query this one is specific for react because they utilize some react hooks in it but if you're not using react as a front end be sure you're not using the react specific create API function I named it API messages just because that matches the file name and let's get started creating our configuration for this the first thing we need to do is write our reducer path this is because rtk query is built on top of and into Redux toolkit so this path is used to register the API into the store it has a default of just API but we want to be a little bit more descriptive and I'm going to call it messages API the next thing we need is our base query now this is what our endpoints are going to be appended onto and it contains all of our base options if you want to add headers which you don't need to or any kind of options that you want every single one of your endpoints to have this is where you would do it and it's in the base query parameter and I'm going to use the function fetch base query and this is coming from the same place the create API function and it holds an object of all kinds of options now you need a base URL it does default to the base path of where the API is called from they really don't recommend that and typically want you to add in your own base URL here I'm gonna do that because our Json server is running on a different port than the application so we do in fact need to specify this the last thing that we need just to set this up is our end points this is a function that gets sent to this build parameter and that is used to create all of our endpoints and functions our first endpoint is going to be get messages and it's going to use a function of a build called query now there's two types of functions that I'm going to be using today the build.query and the build. mutation which I'll go over later build query is what you would use for all of your get requests it takes in an object that requires a query and this is the rest of your url the rest of your endpoint that you're going to be making this call to it is a function that can be sent a parameter for this one all we're going to do is grab every single one of the messages so we just need the messages and that's pretty much all we need to do to set up this API now that the API has been created we need to connect it to our store if you've seen my previous presentation on Redux and Redux toolkit the store should look familiar to you but if it is unfamiliar I would recommend watching that presentation so you have an idea of what's going on the first thing we need to do is add our API to the reducers this is because our TK query is directly built into the store and has its own state and I'm going to go ahead and just copy this in here the next thing we need to do is set up our middleware and I'll do that by just getting the default middleware function and concating it with the messages API middleware if I save this our application will re-render and we can see our new changes under API in our store and you can see that the middleware was registered so if you take a look at our state we have our app profile messages and now messages API which is wonderful and exactly what we want to see now that we've got that set up let's go ahead and start using our API now the first thing we need to do is we need to export our endpoints so export const it's an object from from messages API and one of the things you're going to notice as I type this is that the API actually prepends all of the end points with a use and appends it with either query as it is in this case or mutation as we'll find out later so just keep that in mind as you're writing your end points now let's go ahead and go to our app.json file where our get messages function is which fetches and Returns the messages and sets it in state so one of the benefits of rtk query is all of this is actually now in the messages API all except for this right here so what we're going to do is call our use Query function and grab the data out of it and this line right here is actually the equivalent of these two lines here but without the need to await or process our returned data so we don't need to Json it because it already returns that way it's just already done for us now because we do want to dispatch this these messages into the state I'm going to go ahead and reuse this use effect but I'm going to remove all of this code I'm gonna copy this and then remove all of this code and paste it there I'm going to remove this and now this is all set up and ready to go and if we say this we will be able to see this function being called so as you see here we have our middleware is registered we have a set messages which has this we have a pending another set messages which is empty and fulfilled right so our state now looks and has an empty messages that's not exactly the behavior that we want to have this is because there were two dispatches called this is because there were two dispatches being called before the API had even returned the fulfilled status which means that it had been completed so we're going to go ahead and handle that we're going to do that by adding another one of the returned variables provided by the API and that would be is loading so this variable here is essentially true only the first time this API is called when the component is rendered so if is loading is true the API call hasn't been completed and we don't have data yet so we can use that to say if it's not loading then dispatch our set messages and we also want to make sure that this is called every time is loading is changed right Simply Save this and we refresh we'll see now that we have a pending fulfilled and then set messages is called and if you see the diff we now actually have messages in there which is exactly what we wanted to see but there is another problem if we go to messages and we go back to personal information and back to messages we never end up calling our API again and every time we go back to messages we always want to have the most up-to-date data so to do that it actually makes the most sense to move it out of the app component and into the messages component so to do so we're actually going to remove all of the code that we just wrote because it doesn't need to be here anymore right we'll remove all the unused Imports because they're not necessary we'll save and let's go to the messages component so if we are grabbing our messages from the back end directly in this file we don't actually need messages from our state anymore so one of the things that we're going to do is remove all of this from our messages slice but let's start by just adding the API call right we'll import the function and we will remove the Redux state and the unused Imports and because I like to clean up my code we're gonna go ahead and also remove all of this from State as well we don't need to set the State anymore and we don't need this used select messages selector anymore right and now this set messages reducer is only actually setting the notifications so we're going to rename that as well save that and that'll help us a little later on so if we save this and go to our application refresh go to messages you'll see that the middleware has been configured now only when messages was loaded because it doesn't need to be configured before that and we're going to have our pending and fulfilled which is great but the problem is is that if we go and update our backend with new data and save it we will not actually end up getting that new information and that is because of the way rtk query caches data if you see here we have this unsubscribed and then we went back to messages and the API execute query was rejected that is because it has been less than 60 seconds since this data was added to the state now if we move off of personal information and we're unsubscribed so there's no subscribers to this information anymore and we wait 60 seconds we will be able to see the data expire and when we move back to messages we will be able to refresh it and grab new data and I'll speed this along in the recording thank you okay so you can see here one minute after the unsubscribed we have this queries remove query result now if we go to messages we will actually have the pending and fulfilled for our needs I'm going to show you how to actually Force this to go and fetch new data every time this component is mounted or the arguments change so we're going to go back to our messages and I'm gonna add an object of options to our query function now it is important to note here that if you don't have anything being sent into the endpoint itself you'll need to start it with undefined if we were sending in an index or some kind of value that would be used to create the query or use to modify the returned data in some way then we wouldn't have to do this but because there is nothing being sent in we want to make sure that our object is actually being added to the correct value so undefined and then we're going to have an object and the value we want to use here is called refetch on Mount or Arc change that means that when this component mounts we want to refetch the data we want to recall this API and I'm going to format the file save and you'll see a difference in Behavior now when we move from personal information messages and Back Again so we're gonna go to messages we'll get our first one move back here and then we'll move back to messages and this time it did actually recall the API which is great this does give you a lot more control over how many API calls your application actually makes with us our data is small and it's all local and it's mocked so it doesn't really matter but with much larger applications that may be stored in the cloud and you pay per call this can be really really useful in having more control over everything so if you've noticed the notifications Bell has been has had zero here and there's been nothing in the list that is because we've removed where and when we were adding the messages into the state and updating our notifications list so let's go ahead and get that set up now and our notifications live in app header as you can see down here this notifications pop over and so we're going to start by grabbing our data here and updating this date I'm just going to go ahead and copy and paste this add our import and I'm going to add the use effect that's needed to make this update our notifications right going to save this if we go look at notifications you'll see we ended up having the exact same issue that we had before in which the dispatch is being called before the date is actually ready so we can do the same thing here add is loading if not loading run or dispatch I'm going to format that so that it's a little bit easier to read we're going to add our is loading here so that every time this changes we rerun this use effect save and we'll see that we're now getting data and this is fantastic this is exactly what we were looking for so one of the things we want to do is we want to make sure that notifications is updated periodically at an interval that we choose and we can do this very easily with something called pulling interval it's another one of the options in that array just like the refetch on Mount or args change so let's go set that up undefined again because we're not sending anything into our get messages function we're gonna have our object and pulling interval and pulling interval is defaulted to zero which means that there is no pulling interval and it won't call it any time other than the first time or when we set up some other kind of flag to recall it and it's done in milliseconds so if we wanted to do it every three seconds we would do this 3000. if we save we'll move back over here we'll refresh just to restart the store and you'll start to notice that every three seconds we're calling this API again but if you'll notice it's not calling the use effect and that is because that is loading variable we have only changes the very first time this API is called the variable we actually need for something like this is is fetching so now you'll start to see it's going to set the notifications which is fantastic exactly what we wanted so now we've added this same query the same get messages query in two different components notifications and in messages so I'm going to show you something that's really cool I'm going to set this to a longer interval 10 seconds save that I'm going to update our back end with another message I'm going to save and this hasn't been called and it won't be called and I'm going to move to messages and if you notice we called the API when I moved to messages because we had it set to refetch on Mount right it wasn't quite time yet for the notifications to refetch the data but as soon as we move to messages we refetch the data and updated the store because of the fetch done in messages which means that if you fetch data in one place every other place that that data is read will be updated at the same time so this is really convenient because you don't really want to have to fetch this data in one place put it in the store and then grab it in the other like you would with just Redux now it's all handled out of the box with rtk query which is really convenient because for something like notifications you don't want it to be behind just because it hasn't hit its pulling interval yet your polling interval could be something like five minutes but if you go to messages and you notice that oh hey there's already new notifications those should be shown in your notifications Bell and it was handled without any configuration from us so the next thing I'm going to show you is a mutation and that's any of your posts your puts your deletes any of those kind of calls and we'll do that by updating the code that we have for this star so it does make calls to the back end it's just very slow when the notification Bell ends up refetching these will update which is great and exactly what we want but it's not the best experience to have it take so long for that to be updated if this was me I'd be clicking that star a million times wondering why it hadn't updated yet so let's go and put that in rtk query and I'll show you how easy it is to actually update them the code for this server update call is actually in our messages list item this is the component that holds each of the individual items in the list and that little star and you can see the call here right we have our request options which is put our headers the body which we have to stringify the headers which is application Json we have our ID and body and then we have to await our response and as of right now we're just blocking that response so that we can see that it's actually being run correctly since the UI doesn't update very well so let's start writing our mutation it's going to go into the exact same place as our set messages query and we're going to call it set messages start it uses the same build as before but instead of query we're going to use mutation we also need a query to tell it which end point to use but unlike the get messages query we're actually going to have some input variables we're going to have an object that has ID and we're going to have a body here as well so very similar to how the messages list item had its request options we're going to do something like that here with this query we're gonna have our URL with messages and our ID we're going to have our method and we're gonna instead of Json stringifying our body we're just gonna go ahead and spread our body again if I could spread that correctly I'm gonna go ahead and format this file and then I'm going to export our set messages starred function in the same way we did the query except instead of it ending in query it's going to end in mutation see set Stars messages mutation so I'm going to go ahead and move this back since we don't need to look at that anymore and now what I'm going to do is I'm actually going to replace this entire function with a single line I'm going to remove this and start writing one of the things that's a little different with a mutation over a query is that you don't just automatically get the data you actually get a function that you can use anywhere else in your component and it's got the same name as what we set in our API so in this case it's going to be set messages start and it's going to come from and it's going to come from our use set messages starred mutation this can also return an object of options and return values just like we have our query but that would be here in the second perimeter here we're not going to use any of that just wanted to point that out in case you were wondering if there was more stuff that you could get from this mutation and now we're going to take this and we're going to go ahead and replace this handle toggle start save come here into messages and now we will see our Stars being executed which is exactly what we want except we're not seeing our UI update until our notifications refetches the data there's a really simple fix for this rtk query works on a cache just like we saw when we had to add the refetch on Mount parameter to our messages get call one of the things you can do is add a tag to your queries and invalidate them with mutations and this allows you to say hey I've updated the back end with this mutation so please invalidate all of the cached data that you get with these queries that have this tag this way you know that any information you have on the front end is always the most up-to-date and all you need to do to set this up is change add three lines of code to your API the first thing you need to do is you need a global tag list these are essentially tags that you're going to use in any of your endpoints and you need them to be in this Global tag types array there can be any number in here the names of the tags don't actually matter you can decide all of that yourself so the next thing we're going to do is we're going to provide a tag for our query and that's the provide tags parameter with an array of tags and you can have any number of tags here and then the last thing we're going to do is we're going to say hey our mutation needs to invalidate all of the queries that use this same tag so it uses the invalidates tag array and messages the best part here is you can have one mutation invalidate multiple tags or one query with dozens of tags and they can mix and match and you can have the same tag on multiple queries or invalidate the same tag with multiple mutations so I'm going to save this and we're going to go to messages and I'm going to click this button and we'll see now that the UI updated immediately and this is exactly the kind of behavior that we want to see and so with that we've added all of the rtk query code I wanted to show you today we figured out how to write a get call a put call and some of the options available to you directly out of the box easy to access with rtk query however this isn't all that rtk query is capable of I've touched on a few of these points here and there throughout the coding but it's always worth it to go over these again and in more detail rtk has automatic loading and fetching parameters and we saw those when we added the handling to make sure that the dispatch for the state is only called when the API call has been completed the first time and then when we added the is fetching for the notifications Bell these can be really really handy when you want to do something like set up a loader or a spinner the first time a component is rendered but then after that all you want to do is gray out the data that's already there to say hey this data might not be valid don't touch anything for a second some other things is you no longer really need to write try catch blocks just like is loading and is fetching there's an is error and the error message itself that can just be accessed in those same ways this means you have a lot less boilerplate code that you need to handle which means less for you to maintain yourself there's also built-in support for optimistic rendering now when we were looking at the favoriting and unfavoring of messages we handled that by just invalidating the cache we had zero latency in the return of our API calls because our data was mocked on a Json server but sometimes there can be a delay of seconds and we don't want to just wait on the front end for that response to come back saying hey it's cool here's your new data instead we can set up the optimistic rendering to say hey we expect this update function to complete correctly so let's already show it on the UI then there's no need to wait and we'll get the exact same user experience without having to wait for all of the other backend calls to complete and just like Redux rtk query is UI agnostic which means you can use it with angular react svelte and combine it with all kinds of libraries like the ui5 web components this means that it is an easy choice to make when you're looking for Estate Management and data fetching tool so thank you for watching I hope you've been able to learn more about rtk query and what it is and why it might benefit you in your front-end development world if you have any questions feel free to reach out to me on Twitter or LinkedIn you can also leave a question in the comments below and I will try to answer it thank you again and happy coding
Info
Channel: SAP Developers
Views: 6,531
Rating: undefined out of 5
Keywords:
Id: Wy8HWC2LSo0
Channel Id: undefined
Length: 39min 14sec (2354 seconds)
Published: Tue Oct 04 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.