[{"data":1,"prerenderedAt":918},["ShallowReactive",2],{"page-\u002Fnuxt\u002Frecuperer-des-donnees":3,"pieces-nuxt":871,"autour-\u002Fnuxt\u002Frecuperer-des-donnees":900,"prerequis-\u002Fnuxt\u002Frecuperer-des-donnees":905,"plan-nuxt":907},{"id":4,"title":5,"body":6,"description":838,"extension":839,"ligne":840,"meta":841,"motsCles":842,"navigation":167,"niveau":847,"path":848,"prerequis":849,"ressources":851,"seo":859,"sources":860,"stem":869,"__hash__":870},"docs\u002Fnuxt\u002F05.recuperer-des-donnees.md","Récupérer des données",{"type":7,"value":8,"toc":829},"minimark",[9,14,39,43,55,357,362,435,439,450,454,461,464,468,477,569,583,587,602,659,670,674,683,686,691,778,792,796,825],[10,11,13],"h2",{"id":12},"ce-que-tu-vas-apprendre","Ce que tu vas apprendre",[15,16,17,26,29,32],"ul",{},[18,19,20,21,25],"li",{},"Charger la liste des recettes avec ",[22,23,24],"code",{},"useFetch",".",[18,27,28],{},"Afficher un état de chargement et une erreur.",[18,30,31],{},"Ce qui se passe entre le navigateur et le serveur, étape par étape.",[18,33,34,35,38],{},"Pourquoi ",[22,36,37],{},"$fetch"," seul dans le setup est un piège, et où l'utiliser.",[10,40,42],{"id":41},"charger-la-liste-avec-usefetch","Charger la liste avec useFetch",[44,45,46,47,50,51,54],"p",{},"Ta page ",[22,48,49],{},"\u002Frecettes"," doit afficher les recettes fournies par l'API ",[22,52,53],{},"\u002Fapi\u002Frecettes"," (tu l'écriras au chapitre suivant). Une ligne suffit :",[56,57,63],"pre",{"className":58,"code":59,"filename":60,"language":61,"meta":62,"style":62},"language-vue shiki shiki-themes github-light-default github-dark-default github-dark-default","\u003Cscript setup lang=\"ts\">\nconst { data: recettes, status, error, refresh } = await useFetch('\u002Fapi\u002Frecettes')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cp v-if=\"status === 'pending'\">Chargement...\u003C\u002Fp>\n  \u003Cp v-else-if=\"error\">Impossible de charger les recettes.\u003C\u002Fp>\n  \u003Cul v-else>\n    \u003Cli v-for=\"r in recettes\" :key=\"r.id\">\n      \u003CNuxtLink :to=\"`\u002Frecettes\u002F${r.id}`\">{{ r.titre }}\u003C\u002FNuxtLink>\n    \u003C\u002Fli>\n  \u003C\u002Ful>\n  \u003Cbutton @click=\"refresh()\">Actualiser\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n","app\u002Fpages\u002Frecettes\u002Findex.vue","vue","",[22,64,65,95,152,162,169,179,202,224,236,262,305,315,325,348],{"__ignoreMap":62},[66,67,70,74,78,82,85,88,92],"span",{"class":68,"line":69},"line",1,[66,71,73],{"class":72},"scfrF","\u003C",[66,75,77],{"class":76},"s5JFL","script",[66,79,81],{"class":80},"s5iOY"," setup",[66,83,84],{"class":80}," lang",[66,86,87],{"class":72},"=",[66,89,91],{"class":90},"shWOn","\"ts\"",[66,93,94],{"class":72},">\n",[66,96,98,102,105,109,112,115,118,121,123,126,128,131,134,136,139,143,146,149],{"class":68,"line":97},2,[66,99,101],{"class":100},"sOnC1","const",[66,103,104],{"class":72}," { ",[66,106,108],{"class":107},"sIXEE","data",[66,110,111],{"class":72},": ",[66,113,114],{"class":80},"recettes",[66,116,117],{"class":72},", ",[66,119,120],{"class":80},"status",[66,122,117],{"class":72},[66,124,125],{"class":80},"error",[66,127,117],{"class":72},[66,129,130],{"class":80},"refresh",[66,132,133],{"class":72}," } ",[66,135,87],{"class":100},[66,137,138],{"class":100}," await",[66,140,142],{"class":141},"syCW7"," useFetch",[66,144,145],{"class":72},"(",[66,147,148],{"class":90},"'\u002Fapi\u002Frecettes'",[66,150,151],{"class":72},")\n",[66,153,155,158,160],{"class":68,"line":154},3,[66,156,157],{"class":72},"\u003C\u002F",[66,159,77],{"class":76},[66,161,94],{"class":72},[66,163,165],{"class":68,"line":164},4,[66,166,168],{"emptyLinePlaceholder":167},true,"\n",[66,170,172,174,177],{"class":68,"line":171},5,[66,173,73],{"class":72},[66,175,176],{"class":76},"template",[66,178,94],{"class":72},[66,180,182,185,187,190,192,195,198,200],{"class":68,"line":181},6,[66,183,184],{"class":72},"  \u003C",[66,186,44],{"class":76},[66,188,189],{"class":80}," v-if",[66,191,87],{"class":72},[66,193,194],{"class":90},"\"status === 'pending'\"",[66,196,197],{"class":72},">Chargement...\u003C\u002F",[66,199,44],{"class":76},[66,201,94],{"class":72},[66,203,205,207,209,212,214,217,220,222],{"class":68,"line":204},7,[66,206,184],{"class":72},[66,208,44],{"class":76},[66,210,211],{"class":80}," v-else-if",[66,213,87],{"class":72},[66,215,216],{"class":90},"\"error\"",[66,218,219],{"class":72},">Impossible de charger les recettes.\u003C\u002F",[66,221,44],{"class":76},[66,223,94],{"class":72},[66,225,227,229,231,234],{"class":68,"line":226},8,[66,228,184],{"class":72},[66,230,15],{"class":76},[66,232,233],{"class":80}," v-else",[66,235,94],{"class":72},[66,237,239,242,244,247,249,252,255,257,260],{"class":68,"line":238},9,[66,240,241],{"class":72},"    \u003C",[66,243,18],{"class":76},[66,245,246],{"class":80}," v-for",[66,248,87],{"class":72},[66,250,251],{"class":90},"\"r in recettes\"",[66,253,254],{"class":80}," :key",[66,256,87],{"class":72},[66,258,259],{"class":90},"\"r.id\"",[66,261,94],{"class":72},[66,263,265,268,271,274,277,279,282,285,288,290,293,296,298,301,303],{"class":68,"line":264},10,[66,266,267],{"class":72},"      \u003C",[66,269,270],{"class":76},"NuxtLink",[66,272,273],{"class":72}," :",[66,275,276],{"class":80},"to",[66,278,87],{"class":72},[66,280,281],{"class":72},"\"",[66,283,284],{"class":90},"`\u002Frecettes\u002F${",[66,286,287],{"class":72},"r",[66,289,25],{"class":90},[66,291,292],{"class":72},"id",[66,294,295],{"class":90},"}`",[66,297,281],{"class":72},[66,299,300],{"class":72},">{{ r.titre }}\u003C\u002F",[66,302,270],{"class":76},[66,304,94],{"class":72},[66,306,308,311,313],{"class":68,"line":307},11,[66,309,310],{"class":72},"    \u003C\u002F",[66,312,18],{"class":76},[66,314,94],{"class":72},[66,316,318,321,323],{"class":68,"line":317},12,[66,319,320],{"class":72},"  \u003C\u002F",[66,322,15],{"class":76},[66,324,94],{"class":72},[66,326,328,330,333,336,338,341,344,346],{"class":68,"line":327},13,[66,329,184],{"class":72},[66,331,332],{"class":76},"button",[66,334,335],{"class":80}," @click",[66,337,87],{"class":72},[66,339,340],{"class":90},"\"refresh()\"",[66,342,343],{"class":72},">Actualiser\u003C\u002F",[66,345,332],{"class":76},[66,347,94],{"class":72},[66,349,351,353,355],{"class":68,"line":350},14,[66,352,157],{"class":72},[66,354,176],{"class":76},[66,356,94],{"class":72},[44,358,359,361],{},[22,360,24],{}," renvoie plusieurs choses utiles :",[363,364,365,378],"table",{},[366,367,368],"thead",{},[369,370,371,375],"tr",{},[372,373,374],"th",{},"Valeur",[372,376,377],{},"Rôle",[379,380,381,395,416,425],"tbody",{},[369,382,383,388],{},[384,385,386],"td",{},[22,387,108],{},[384,389,390,391,394],{},"Les données reçues (",[22,392,393],{},"undefined"," tant qu'il n'y a rien).",[369,396,397,401],{},[384,398,399],{},[22,400,120],{},[384,402,403,117,406,117,409,412,413,25],{},[22,404,405],{},"'idle'",[22,407,408],{},"'pending'",[22,410,411],{},"'success'"," ou ",[22,414,415],{},"'error'",[369,417,418,422],{},[384,419,420],{},[22,421,125],{},[384,423,424],{},"L'erreur, s'il y en a une.",[369,426,427,432],{},[384,428,429],{},[22,430,431],{},"refresh()",[384,433,434],{},"Relance la requête.",[10,436,438],{"id":437},"ce-qui-se-passe-vraiment","Ce qui se passe vraiment",[44,440,441,442,444,445,449],{},"Au premier chargement, la page est fabriquée sur le serveur. ",[22,443,24],{}," y appelle l'API, puis le serveur envoie au navigateur le HTML ",[446,447,448],"strong",{},"et"," les données. Lance l'animation pour suivre la requête :",[451,452],"flux-donnees",{"scenario":453},"premier-chargement",[44,455,456,457,460],{},"Quand tu cliques ensuite sur un ",[22,458,459],{},"\u003CNuxtLink>",", tout se passe dans le navigateur : seules les données voyagent.",[451,462],{"scenario":463},"navigation",[10,465,467],{"id":466},"une-adresse-qui-change","Une adresse qui change",[44,469,470,471,473,474,476],{},"Sur la page d'une recette, l'adresse de l'API dépend du paramètre ",[22,472,292],{},". Passe une fonction plutôt qu'un texte : ",[22,475,24],{}," relance la requête quand la valeur change.",[56,478,481],{"className":58,"code":479,"filename":480,"language":61,"meta":62,"style":62},"\u003Cscript setup lang=\"ts\">\nconst route = useRoute()\nconst { data: recette } = await useFetch(() => `\u002Fapi\u002Frecettes\u002F${route.params.id}`)\n\u003C\u002Fscript>\n","app\u002Fpages\u002Frecettes\u002F[id].vue",[22,482,483,499,515,561],{"__ignoreMap":62},[66,484,485,487,489,491,493,495,497],{"class":68,"line":69},[66,486,73],{"class":72},[66,488,77],{"class":76},[66,490,81],{"class":80},[66,492,84],{"class":80},[66,494,87],{"class":72},[66,496,91],{"class":90},[66,498,94],{"class":72},[66,500,501,503,506,509,512],{"class":68,"line":97},[66,502,101],{"class":100},[66,504,505],{"class":80}," route",[66,507,508],{"class":100}," =",[66,510,511],{"class":141}," useRoute",[66,513,514],{"class":72},"()\n",[66,516,517,519,521,523,525,528,530,532,534,536,539,542,545,548,550,553,555,557,559],{"class":68,"line":154},[66,518,101],{"class":100},[66,520,104],{"class":72},[66,522,108],{"class":107},[66,524,111],{"class":72},[66,526,527],{"class":80},"recette",[66,529,133],{"class":72},[66,531,87],{"class":100},[66,533,138],{"class":100},[66,535,142],{"class":141},[66,537,538],{"class":72},"(() ",[66,540,541],{"class":100},"=>",[66,543,544],{"class":90}," `\u002Fapi\u002Frecettes\u002F${",[66,546,547],{"class":72},"route",[66,549,25],{"class":90},[66,551,552],{"class":72},"params",[66,554,25],{"class":90},[66,556,292],{"class":72},[66,558,295],{"class":90},[66,560,151],{"class":72},[66,562,563,565,567],{"class":68,"line":164},[66,564,157],{"class":72},[66,566,77],{"class":76},[66,568,94],{"class":72},[44,570,571,572,575,576,579,580,25],{},"Tu peux aussi envoyer des paramètres d'adresse avec l'option ",[22,573,574],{},"query"," : ",[22,577,578],{},"useFetch('\u002Fapi\u002Frecettes', { query: { categorie: 'dessert' } })"," appelle ",[22,581,582],{},"\u002Fapi\u002Frecettes?categorie=dessert",[10,584,586],{"id":585},"useasyncdata-pour-tout-le-reste","useAsyncData : pour tout le reste",[44,588,589,591,592,595,596,117,598,117,600,25],{},[22,590,24],{}," sert à appeler une adresse. Pour une autre source (une bibliothèque comme le client Supabase, un calcul), utilise ",[22,593,594],{},"useAsyncData",". Il fonctionne de la même façon : données transmises du serveur au navigateur, ",[22,597,120],{},[22,599,125],{},[22,601,130],{},[56,603,607],{"className":604,"code":605,"language":606,"meta":62,"style":62},"language-ts shiki shiki-themes github-light-default github-dark-default github-dark-default","const { data: recettes } = await useAsyncData('recettes', () => client.from('recettes').select())\n","ts",[22,608,609],{"__ignoreMap":62},[66,610,611,613,615,617,619,621,623,625,627,630,632,635,638,640,643,646,648,650,653,656],{"class":68,"line":69},[66,612,101],{"class":100},[66,614,104],{"class":72},[66,616,108],{"class":107},[66,618,111],{"class":72},[66,620,114],{"class":80},[66,622,133],{"class":72},[66,624,87],{"class":100},[66,626,138],{"class":100},[66,628,629],{"class":141}," useAsyncData",[66,631,145],{"class":72},[66,633,634],{"class":90},"'recettes'",[66,636,637],{"class":72},", () ",[66,639,541],{"class":100},[66,641,642],{"class":72}," client.",[66,644,645],{"class":141},"from",[66,647,145],{"class":72},[66,649,634],{"class":90},[66,651,652],{"class":72},").",[66,654,655],{"class":141},"select",[66,657,658],{"class":72},"())\n",[44,660,661,662,664,665,667,668,25],{},"Le premier argument est une clé qui identifie la donnée. En réalité, ",[22,663,24],{}," est un raccourci pour ",[22,666,594],{}," + ",[22,669,37],{},[10,671,673],{"id":672},"le-piège-de-fetch","Le piège de $fetch",[44,675,676,678,679,682],{},[22,677,37],{}," envoie une requête, tout simplement. Mais placé seul dans le ",[22,680,681],{},"\u003Cscript setup>"," d'une page, il s'exécute deux fois : une fois sur le serveur, une fois dans le navigateur, car il ne transmet pas son résultat.",[451,684],{"scenario":685},"piege-fetch",[44,687,688,690],{},[22,689,37],{}," reste le bon outil pour les actions déclenchées par l'utilisateur, comme l'envoi d'un formulaire :",[56,692,694],{"className":604,"code":693,"language":606,"meta":62,"style":62},"async function ajouterRecette(nouvelle: { titre: string, duree: number }) {\n  await $fetch('\u002Fapi\u002Frecettes', { method: 'POST', body: nouvelle })\n  await refresh() \u002F\u002F recharge la liste\n}\n",[22,695,696,738,759,773],{"__ignoreMap":62},[66,697,698,701,704,707,709,712,715,717,720,722,725,727,730,732,735],{"class":68,"line":69},[66,699,700],{"class":100},"async",[66,702,703],{"class":100}," function",[66,705,706],{"class":141}," ajouterRecette",[66,708,145],{"class":72},[66,710,711],{"class":107},"nouvelle",[66,713,714],{"class":100},":",[66,716,104],{"class":72},[66,718,719],{"class":107},"titre",[66,721,714],{"class":100},[66,723,724],{"class":80}," string",[66,726,117],{"class":72},[66,728,729],{"class":107},"duree",[66,731,714],{"class":100},[66,733,734],{"class":80}," number",[66,736,737],{"class":72}," }) {\n",[66,739,740,743,746,748,750,753,756],{"class":68,"line":97},[66,741,742],{"class":100},"  await",[66,744,745],{"class":141}," $fetch",[66,747,145],{"class":72},[66,749,148],{"class":90},[66,751,752],{"class":72},", { method: ",[66,754,755],{"class":90},"'POST'",[66,757,758],{"class":72},", body: nouvelle })\n",[66,760,761,763,766,769],{"class":68,"line":154},[66,762,742],{"class":100},[66,764,765],{"class":141}," refresh",[66,767,768],{"class":72},"() ",[66,770,772],{"class":771},"sd6ml","\u002F\u002F recharge la liste\n",[66,774,775],{"class":68,"line":164},[66,776,777],{"class":72},"}\n",[779,780,781],"warning",{},[44,782,783,785,786,789,790,25],{},[22,784,108],{}," ne suit pas les modifications à l'intérieur de l'objet. Pour changer une recette affichée, remplace la valeur entière (",[22,787,788],{},"data.value = { ...data.value, titre: 'Nouveau titre' }",") ou recharge avec ",[22,791,431],{},[10,793,795],{"id":794},"à-retenir","À retenir",[15,797,798,806,817,820],{},[18,799,800,802,803,805],{},[22,801,24],{}," charge une adresse, ",[22,804,594],{}," n'importe quelle fonction : les deux transmettent les données du serveur au navigateur.",[18,807,808,810,811,813,814,816],{},[22,809,120],{}," et ",[22,812,125],{}," gèrent l'attente et les erreurs ; ",[22,815,431],{}," relance.",[18,818,819],{},"Passe une fonction en adresse pour qu'elle suive les changements de paramètre.",[18,821,822,824],{},[22,823,37],{}," pour les clics et les formulaires, jamais seul dans le setup.",[826,827,828],"style",{},"html pre.shiki code .scfrF, html code.shiki .scfrF{--shiki-light:#1F2328;--shiki-default:#E6EDF3;--shiki-dark:#E6EDF3}html pre.shiki code .s5JFL, html code.shiki .s5JFL{--shiki-light:#116329;--shiki-default:#7EE787;--shiki-dark:#7EE787}html pre.shiki code .s5iOY, html code.shiki .s5iOY{--shiki-light:#0550AE;--shiki-default:#79C0FF;--shiki-dark:#79C0FF}html pre.shiki code .shWOn, html code.shiki .shWOn{--shiki-light:#0A3069;--shiki-default:#A5D6FF;--shiki-dark:#A5D6FF}html pre.shiki code .sOnC1, html code.shiki .sOnC1{--shiki-light:#CF222E;--shiki-default:#FF7B72;--shiki-dark:#FF7B72}html pre.shiki code .sIXEE, html code.shiki .sIXEE{--shiki-light:#953800;--shiki-default:#FFA657;--shiki-dark:#FFA657}html pre.shiki code .syCW7, html code.shiki .syCW7{--shiki-light:#8250DF;--shiki-default:#D2A8FF;--shiki-dark:#D2A8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sd6ml, html code.shiki .sd6ml{--shiki-light:#6E7781;--shiki-default:#8B949E;--shiki-dark:#8B949E}",{"title":62,"searchDepth":97,"depth":154,"links":830},[831,832,833,834,835,836,837],{"id":12,"depth":97,"text":13},{"id":41,"depth":97,"text":42},{"id":437,"depth":97,"text":438},{"id":466,"depth":97,"text":467},{"id":585,"depth":97,"text":586},{"id":672,"depth":97,"text":673},{"id":794,"depth":97,"text":795},"Charger des données avec useFetch, gérer le chargement et les erreurs, et savoir quand utiliser $fetch.","md","nuxt",{},[24,594,37,843,844,120,130,845,846],"données","chargement","payload","hydratation","intermediaire","\u002Fnuxt\u002Frecuperer-des-donnees",[850],"\u002Fnuxt\u002Fcomposants",[852,856],{"nom":853,"url":854,"type":855,"anglais":167},"Documentation officielle de Nuxt","https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fgetting-started\u002Fdata-fetching","doc",{"nom":857,"url":858,"type":855},"HTTP sur MDN","https:\u002F\u002Fdeveloper.mozilla.org\u002Ffr\u002Fdocs\u002FWeb\u002FHTTP",{"title":5,"description":838},[861,863,866],{"nom":862,"url":854},"Récupération des données (en anglais)",{"nom":864,"url":865},"useFetch (en anglais)","https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fapi\u002Fcomposables\u002Fuse-fetch",{"nom":867,"url":868},"useAsyncData (en anglais)","https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fapi\u002Fcomposables\u002Fuse-async-data","nuxt\u002F05.recuperer-des-donnees","WDVPuEM6iGGeetVLBapC209HElEg8Gc2-qkKGvmuSEE",[872,876,880,884,887,888,892,896],{"path":873,"title":874,"stem":875},"\u002Fnuxt\u002Fintroduction","Introduction à Nuxt","nuxt\u002F01.introduction",{"path":877,"title":878,"stem":879},"\u002Fnuxt\u002Fstructure","La structure d'un projet","nuxt\u002F02.structure",{"path":881,"title":882,"stem":883},"\u002Fnuxt\u002Fpages-et-routage","Pages et routage","nuxt\u002F03.pages-et-routage",{"path":850,"title":885,"stem":886},"Les composants","nuxt\u002F04.composants",{"path":848,"title":5,"stem":869},{"path":889,"title":890,"stem":891},"\u002Fnuxt\u002Froutes-api","Les routes API","nuxt\u002F06.routes-api",{"path":893,"title":894,"stem":895},"\u002Fnuxt\u002Fmodes-de-rendu","Les modes de rendu","nuxt\u002F07.modes-de-rendu",{"path":897,"title":898,"stem":899},"\u002Fnuxt","Nuxt","nuxt\u002Findex",[901,903],{"title":885,"path":850,"stem":886,"description":902,"children":-1},"Découper l'interface en composants importés automatiquement, leur passer des données et charger les plus lourds à la demande.",{"title":890,"path":889,"stem":891,"description":904,"children":-1},"Écrire une petite API dans server\u002Fapi : lire, créer, renvoyer des erreurs, et garder les secrets côté serveur.",[906],{"path":850,"title":885,"ligne":840},[908,910,911,912,913,914,915,916],{"path":873,"title":874,"niveau":909,"stem":875},"debutant",{"path":877,"title":878,"niveau":909,"stem":879},{"path":881,"title":882,"niveau":909,"stem":883},{"path":850,"title":885,"niveau":909,"stem":886},{"path":848,"title":5,"niveau":847,"stem":869},{"path":889,"title":890,"niveau":847,"stem":891},{"path":893,"title":894,"niveau":847,"stem":895},{"path":897,"title":898,"niveau":917,"stem":899},"memo",1794583440331]