{"id":64406,"date":"2024-08-26T20:48:35","date_gmt":"2024-08-26T15:18:35","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=64406"},"modified":"2024-08-26T21:42:20","modified_gmt":"2024-08-26T16:12:20","slug":"data-fetching-in-reactjs-nextjs-with-useswr","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/data-fetching-in-reactjs-nextjs-with-useswr\/","title":{"rendered":"Data fetching in ReactJS\/NextJS with useSWR"},"content":{"rendered":"<p>&#8220;Steve Jobs once said, &#8216;Innovation distinguishes between a leader and a follower.&#8217; The same applies to web development.&#8221;<\/p>\n<p>So let\u2019s go beyond <strong>useEffect<\/strong> and learn a new way of data fetching using <strong>useSWR<\/strong>. Before diving deep into the working of useSWR you first need to understand what useSWR is and why you need to use it over useEffect.<\/p>\n<h2><strong>What is useSWR?<\/strong><\/h2>\n<p><strong>useSWR<\/strong> is a third-party React hook library (by Vercel) designed to simplify data fetching by providing built-in features like caching, revalidation, focus re-fetching, and error handling out of the box.<\/p>\n<p>SWR stands for Stale-While-Revalidate. The Stale-While-Revalidate concept means that while SWR is revalidating the data, it serves the stale data from the cache, ensuring that your data is always fresh.<\/p>\n<h2><strong>Why choose useSWR over useEffect?<\/strong><\/h2>\n<p>Handling loading states, revalidating data, prefetching, error management, and managing multiple API calls with <strong>useEffect<\/strong> can be cumbersome. It often requires writing boilerplate code to handle loading states, caching, and error handling.<\/p>\n<p>useSWR abstracts away much of this complexity, allowing you to focus on the logic specific to your application. Now you are going to understand how useSWR hook works and how you can implement it in your ReactJS\/NextJS project.<\/p>\n<h2><strong>Essentials of useSWR<\/strong><\/h2>\n<p>useSWR accepts three parameters, the third parameter is optional which determines the way the data is handled and the first two parameters determine what is going to be fetched and how it will be fetched. Also, useSWR hook returns five values. We will discuss these params and values briefly in the upcoming section.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64369\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet01.png\" alt=\"structure of useSWR\" width=\"712\" height=\"63\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet01.png 960w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet01-300x27.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet01-768x68.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet01-624x55.png 624w\" sizes=\"(max-width: 712px) 100vw, 712px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Parameters<\/strong><\/span><\/p>\n<ul>\n<li><strong>key<\/strong>: key param is typically a string (often a URL) or an array or an object. The reason for the <strong>key<\/strong> name is because it actually is a unique identifier for the data being fetched. During global mutations, the key of a useSWR hook is used to make changes specific to that hook. So if you use the same key in different components, they will share the same cache.<\/li>\n<li><strong>fetcher<\/strong>: fetcher param is a function that is responsible for fetching the data and returns a promise.<\/li>\n<\/ul>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64370\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet02_a.png\" alt=\"fetcher function\" width=\"552\" height=\"59\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet02_a.png 702w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet02_a-300x32.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet02_a-624x67.png 624w\" sizes=\"(max-width: 552px) 100vw, 552px\" \/><\/p>\n<p style=\"padding-left: 40px;\">You can also use \u2018<span style=\"color: #339966;\">axios<\/span>\u2019 instead of fetch api. The argument <span style=\"color: #ff9900;\">url<\/span> passed into the fetcher function is the key param of useSWR.<\/p>\n<p style=\"padding-left: 40px;\">By default key is the only argument for the fetcher but what if you need more arguments for the fetcher function? In this case, you need an array as key which allows you to pass multiple arguments to the fetcher function. Let\u2019s take an example to understand this better. Suppose you have an API endpoint that requires both a userId and a token to fetch user data.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64371\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet03_a.png\" alt=\"fetcher function\" width=\"553\" height=\"173\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet03_a.png 799w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet03_a-300x94.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet03_a-768x240.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet03_a-624x195.png 624w\" sizes=\"(max-width: 553px) 100vw, 553px\" \/><\/p>\n<p style=\"padding-left: 40px;\">This is not the correct way because url &#8216;<span style=\"color: #339966;\">\/api\/user<\/span>&#8216; does not include <span style=\"color: #ff9900;\">userId<\/span> or <span style=\"color: #ff9900;\">token<\/span>, and if any of these changed useSWR would still use the same cached key and return the previous data as cached data is mapped with a unique key and must be unique.<\/p>\n<p style=\"padding-left: 40px;\">To tackle this, you would have to pass these arguments either as an array or an object.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64372\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet04_a.png\" alt=\"fetcher function\" width=\"556\" height=\"175\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet04_a.png 788w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet04_a-300x94.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet04_a-768x242.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet04_a-624x196.png 624w\" sizes=\"(max-width: 556px) 100vw, 556px\" \/><\/p>\n<p style=\"padding-left: 40px;\">The <span style=\"color: #ff9900;\">url<\/span>, <span style=\"color: #ff9900;\">userId<\/span>, and <span style=\"color: #ff9900;\">token<\/span> are now all included in the key parameter, so any changes to userId or token will cause useSWR to use a different cached key, ensuring that the correct data is provided.<\/p>\n<ul>\n<li><strong>options<\/strong>: The third optional parameter, options, is an object that allows you to customize how your fetched data is managed. This includes controlling when the data should be revalidated, when to retry fetching and specifying actions for both successful and failed requests. Below are some of the options properties:<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul style=\"list-style-type: circle;\">\n<li><strong>refreshInterval<\/strong>: Takes a number and automatically re-fetch the data after the specified interval (in milliseconds). By default disabled (refreshInterval = 0).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64373\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet05_a.png\" alt=\"refreshInterval\" width=\"377\" height=\"135\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet05_a.png 477w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet05_a-300x108.png 300w\" sizes=\"(max-width: 377px) 100vw, 377px\" \/><\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul style=\"list-style-type: circle;\">\n<li><strong>revalidateOnFocus<\/strong>: Takes boolean value and re-fetch the data when the window regains focus. By default true.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64374\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet06_a.png\" alt=\"revalidateOnFocus\" width=\"385\" height=\"116\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet06_a.png 490w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet06_a-300x91.png 300w\" sizes=\"(max-width: 385px) 100vw, 385px\" \/><\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul style=\"list-style-type: circle;\">\n<li><strong>errorRetryInterval<\/strong>: Takes a number and waits till the specified interval (in milliseconds) before retrying a request after it fails. By default 5000 (5 seconds).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64375\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet07_a.png\" alt=\"errorRetryInterval\" width=\"533\" height=\"137\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet07_a.png 680w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet07_a-300x77.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet07_a-624x161.png 624w\" sizes=\"(max-width: 533px) 100vw, 533px\" \/><\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul style=\"list-style-type: circle;\">\n<li><strong>errorRetryCount<\/strong>: Takes a number and controls the number of times useSWR will retry a request when an error occurs. By default 8.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64376\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet08_a.png\" alt=\"errorRetryCount\" width=\"402\" height=\"142\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet08_a.png 487w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet08_a-300x106.png 300w\" sizes=\"(max-width: 402px) 100vw, 402px\" \/><\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul style=\"list-style-type: circle;\">\n<li><strong>onSuccess<\/strong> and <strong>onError<\/strong>: It\u2019s a callback function that runs when the request succeeds or throws an error respectively.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64377\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet09_a.png\" alt=\"onSuccess and onError\" width=\"595\" height=\"198\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet09_a.png 772w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet09_a-300x100.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet09_a-768x256.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet09_a-624x208.png 624w\" sizes=\"(max-width: 595px) 100vw, 595px\" \/><\/p>\n<p style=\"padding-left: 40px;\">Below is the combined options example.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64378\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet10_a.png\" alt=\"combined example\" width=\"671\" height=\"300\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet10_a.png 904w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet10_a-300x134.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet10_a-768x343.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet10_a-624x279.png 624w\" sizes=\"(max-width: 671px) 100vw, 671px\" \/><\/p>\n<p>You have covered some of the parameters section that you need to pass in useSWR, now moving towards the response section that you are getting from useSWR.<\/p>\n<p>As earlier mentioned above, useSWR returns a total of five values in response. Let\u2019s understand what it is.<\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Response<\/strong><\/span><\/p>\n<ul>\n<li><strong>data<\/strong>: it is the data returned from the request to the given key. If the data is not yet available in that case it is undefined.<\/li>\n<li><strong>error<\/strong>: It is an error object if the request failed, or <strong>undefined<\/strong> if there is no error.<\/li>\n<li><strong>isLoading<\/strong>: It\u2019s a boolean returned value that indicates that data is currently being fetched.<\/li>\n<li><strong>isValidating<\/strong>: It\u2019s a boolean returned value that indicates that there is an ongoing request or revalidation is loading.<\/li>\n<li><strong>mutate<\/strong>: It\u2019s a function for making changes to the cached data specific to a given cached key only.<\/li>\n<\/ul>\n<p>You have completed the basics of useSWR, below is the full-scale example.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-64379\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet11_a.png\" alt=\"complete useSWR example\" width=\"827\" height=\"875\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet11_a.png 827w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet11_a-284x300.png 284w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet11_a-768x813.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet11_a-624x660.png 624w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet11_a-24x24.png 24w\" sizes=\"(max-width: 827px) 100vw, 827px\" \/><\/p>\n<h2><strong>Advanced topics related to useSWR<\/strong><\/h2>\n<p>In this section, you will see some advanced topics related to useSWR that can help you unlock its full potential in your ReactJS or NextJS applications.<\/p>\n<h2><strong>Conditional fetching<\/strong><\/h2>\n<p>Sometimes, you need to fetch data that depends on the result of another request. useSWR allows you to conditionally fetch data based on the availability of a key or another piece of data.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64380\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet12.png\" alt=\"conditional fetching\" width=\"668\" height=\"77\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet12.png 902w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet12-300x35.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet12-768x89.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet12-624x72.png 624w\" sizes=\"(max-width: 668px) 100vw, 668px\" \/><\/p>\n<p>Here fetching posts of a user only after the user&#8217;s data is successfully retrieved.<\/p>\n<h2><strong>Optimistic UI updates<\/strong><\/h2>\n<p>Optimistic UI updates allow you to update the UI immediately after an action, even before the server confirms the change. useSWR\u2019s <strong>mutate<\/strong> function can be used for this purpose.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64381\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet13_a.png\" alt=\"optimistic ui updates\" width=\"654\" height=\"136\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet13_a.png 866w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet13_a-300x62.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet13_a-768x160.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet13_a-624x130.png 624w\" sizes=\"(max-width: 654px) 100vw, 654px\" \/><\/p>\n<h2><strong>Caching strategies<\/strong><\/h2>\n<p>You can make changes to the default cache using useSWRConfig hook.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64382\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet14_a.png\" alt=\"caching strategy\" width=\"733\" height=\"537\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet14_a.png 1003w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet14_a-300x220.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet14_a-768x563.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet14_a-624x457.png 624w\" sizes=\"(max-width: 733px) 100vw, 733px\" \/><\/p>\n<p>As seen above, you can update the default cache by two methods: first is directly by <strong>cache.set()<\/strong> method (commented code line 16) and the second is by mutate function given by useSWRConfig hook.<\/p>\n<p>But you should never update the cache directly. When you update the cache directly (e.g., using cache.set), other components or hooks that rely on that cache might not be aware of the update since it bypasses SWR&#8217;s built-in revalidation mechanism. This can lead to inconsistencies in your UI because those components won&#8217;t automatically re-render or re-fetch data based on the new cache value which results from your application continuing to display outdated data.<\/p>\n<p>So, to overcome all of this you should always use the mutate function for caching updates. The mutate function not only updates the cache but also triggers revalidation or re-rendering of components that use the affected data. This ensures that all parts of your application remain in sync with the updated data.<\/p>\n<h2><strong>Pagination<\/strong><\/h2>\n<p>Implementing pagination using useSWR can be achieved by managing the page state and fetching data for each page.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64383\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a.png\" alt=\"pagination\" width=\"770\" height=\"771\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a.png 865w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a-300x300.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a-150x150.png 150w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a-768x769.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a-624x625.png 624w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a-120x120.png 120w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a-24x24.png 24w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a-48x48.png 48w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet15_a-96x96.png 96w\" sizes=\"(max-width: 770px) 100vw, 770px\" \/><\/p>\n<p>Above is an example of infinite loading and clicking the &#8220;Load More&#8221; button increments the <strong>page<\/strong> state, triggering a new fetch for the next set of data. When the data is successfully fetched (<strong>onSuccess<\/strong>), it appends the new data to the <strong>posts<\/strong> array.<\/p>\n<p>However, this can also be achieved by <strong>useSWRInfinite<\/strong> hook, which is specifically designed for handling paginated data fetching, such as infinite scrolling. useSWRInfinite simplifies the process by automatically managing the pagination logic.<\/p>\n<p>useSWRInfinite allows you to fetch data in pages, with each page being loaded sequentially. The key feature of useSWRInfinite is the <strong>getKey<\/strong> function, which defines the key for each page based on the page index.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-64385\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet16_a.png\" alt=\"pagination using useSWRInfinite\" width=\"835\" height=\"704\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet16_a.png 1049w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet16_a-300x253.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet16_a-1024x863.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet16_a-768x647.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/08\/snippet16_a-624x526.png 624w\" sizes=\"(max-width: 835px) 100vw, 835px\" \/><\/p>\n<p>You might be wondering about <strong>pageIndex<\/strong> and <strong>previousPageData<\/strong>. Let\u2019s understand this.<\/p>\n<p>PageIndex is a parameter automatically supplied by the useSWRInfinite hook. This is a number representing the current page being fetched. It starts from 0 for the first page, 1 for the second page, and so on. The useSWRInfinite hook internally manages the pagination logic and keeps track of how many pages have been requested so far. Each time you call <strong>setSize(size + 1)<\/strong>, indicating that you want to fetch the next page, useSWRInfinite increments the pageIndex and then calls the getKey function with the updated pageIndex.<\/p>\n<p>Also, the previousPageData parameter plays an important role in determining whether to continue fetching more data and how to construct the key for the next page. This parameter represents the data returned from the previous page fetch. It allows you to inspect the result of the last request to decide whether to fetch more data or not.<\/p>\n<p>When fetching the first page, previousPageData is <span style=\"color: #ff9900;\">null<\/span> and for subsequent pages, previousPageData contains the data that was fetched for the previous pageIndex.<\/p>\n<h2><strong>Conclusion<\/strong><\/h2>\n<p>By mastering useSWR, you unlock a powerful tool for efficient data fetching and state management in your React applications. Whether you&#8217;re building complex features like pagination or simply optimizing API calls, useSWR provides the flexibility and performance you need to deliver seamless user experiences.<\/p>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;Steve Jobs once said, &#8216;Innovation distinguishes between a leader and a follower.&#8217; The same applies to web development.&#8221; So let\u2019s go beyond useEffect and learn a new way of data fetching using useSWR. Before diving deep into the working of useSWR you first need to understand what useSWR is and why you need to use [&hellip;]<\/p>\n","protected":false},"author":1923,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":48},"categories":[5876],"tags":[6306,5596,2046,5296,6304,6305],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/64406"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1923"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=64406"}],"version-history":[{"count":3,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/64406\/revisions"}],"predecessor-version":[{"id":64608,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/64406\/revisions\/64608"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=64406"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=64406"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=64406"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}