[{"data":1,"prerenderedAt":857},["ShallowReactive",2],{"blog-post:url-search-params":3},{"id":4,"title":5,"body":6,"date":846,"description":847,"draft":848,"extension":849,"lastModified":850,"meta":851,"navigation":156,"path":852,"readingTime":853,"seo":854,"stem":855,"__hash__":856},"posts\u002Fblog\u002Furl-search-params.md","Cleaner way of dealing with query params using URLSearchParams",{"type":7,"value":8,"toc":844},"minimark",[9,13,16,76,83,101,115,376,383,550,556,655,666,669,679,797,810,813,840],[10,11,12],"p",{},"Ever had a situation where you are supposed to convert an object (key, values)\ninto a query parameter and build a URL around it?",[10,14,15],{},"Here's an example:",[17,18,23],"pre",{"className":19,"code":20,"language":21,"meta":22,"style":22},"language-js shiki shiki-themes github-dark","let user = {\n  name: \"John Doe\",\n  age: 24,\n};\n","js","",[24,25,26,45,58,70],"code",{"__ignoreMap":22},[27,28,31,35,39,42],"span",{"class":29,"line":30},"line",1,[27,32,34],{"class":33},"snl16","let",[27,36,38],{"class":37},"s95oV"," user ",[27,40,41],{"class":33},"=",[27,43,44],{"class":37}," {\n",[27,46,48,51,55],{"class":29,"line":47},2,[27,49,50],{"class":37},"  name: ",[27,52,54],{"class":53},"sU2Wk","\"John Doe\"",[27,56,57],{"class":37},",\n",[27,59,61,64,68],{"class":29,"line":60},3,[27,62,63],{"class":37},"  age: ",[27,65,67],{"class":66},"sDLfK","24",[27,69,57],{"class":37},[27,71,73],{"class":29,"line":72},4,[27,74,75],{"class":37},"};\n",[10,77,78,79,82],{},"Let's say the URL that we want to build \u002F API requires the fields of the above\nobject to be as ",[24,80,81],{},"?name=..&age=..",".",[10,84,85,86,89,90,93,94,97,98,82],{},"The most straightforward way of doing this would be looping through keys of the\n",[24,87,88],{},"object"," and manually appending the key\u002Fvalues to a ",[24,91,92],{},"String"," while separating\neach value with an ",[24,95,96],{},"&",". Oh and don't forget to URL encode each value using\n",[24,99,100],{},"encodeURIComponent",[10,102,103,104,107,108,111,112,82],{},"For example: ",[24,105,106],{},"John Doe"," should be encoded as ",[24,109,110],{},"John%20Doe"," or ",[24,113,114],{},"John+Doe",[17,116,118],{"className":19,"code":117,"language":21,"meta":22,"style":22},"let obj = {\n  name: \"John Doe\",\n  age: 24,\n};\n\nfunction buildQuery(obj) {\n  let query = \"\";\n  Object.entries(obj).forEach(([key, val], currentIndex, entries) => {\n    let keyValPair = `${key}=${encodeURIComponent(val)}`;\n    if (currentIndex !== entries.length - 1) {\n      keyValPair += \"&\"; \u002F\u002F PS: Don't want URLs ending with '&' :)\n    }\n    query += keyValPair;\n  });\n  return query;\n}\n\nbuildQuery(obj);\n\u002F\u002F Output: \"name=John%20Doe&age=20\"\n",[24,119,120,131,139,147,151,158,178,195,240,273,299,318,324,335,341,350,356,361,370],{"__ignoreMap":22},[27,121,122,124,127,129],{"class":29,"line":30},[27,123,34],{"class":33},[27,125,126],{"class":37}," obj ",[27,128,41],{"class":33},[27,130,44],{"class":37},[27,132,133,135,137],{"class":29,"line":47},[27,134,50],{"class":37},[27,136,54],{"class":53},[27,138,57],{"class":37},[27,140,141,143,145],{"class":29,"line":60},[27,142,63],{"class":37},[27,144,67],{"class":66},[27,146,57],{"class":37},[27,148,149],{"class":29,"line":72},[27,150,75],{"class":37},[27,152,154],{"class":29,"line":153},5,[27,155,157],{"emptyLinePlaceholder":156},true,"\n",[27,159,161,164,168,171,175],{"class":29,"line":160},6,[27,162,163],{"class":33},"function",[27,165,167],{"class":166},"svObZ"," buildQuery",[27,169,170],{"class":37},"(",[27,172,174],{"class":173},"s9osk","obj",[27,176,177],{"class":37},") {\n",[27,179,181,184,187,189,192],{"class":29,"line":180},7,[27,182,183],{"class":33},"  let",[27,185,186],{"class":37}," query ",[27,188,41],{"class":33},[27,190,191],{"class":53}," \"\"",[27,193,194],{"class":37},";\n",[27,196,198,201,204,207,210,213,216,219,222,225,228,230,232,235,238],{"class":29,"line":197},8,[27,199,200],{"class":37},"  Object.",[27,202,203],{"class":166},"entries",[27,205,206],{"class":37},"(obj).",[27,208,209],{"class":166},"forEach",[27,211,212],{"class":37},"(([",[27,214,215],{"class":173},"key",[27,217,218],{"class":37},", ",[27,220,221],{"class":173},"val",[27,223,224],{"class":37},"], ",[27,226,227],{"class":173},"currentIndex",[27,229,218],{"class":37},[27,231,203],{"class":173},[27,233,234],{"class":37},") ",[27,236,237],{"class":33},"=>",[27,239,44],{"class":37},[27,241,243,246,249,251,254,256,259,261,263,265,268,271],{"class":29,"line":242},9,[27,244,245],{"class":33},"    let",[27,247,248],{"class":37}," keyValPair ",[27,250,41],{"class":33},[27,252,253],{"class":53}," `${",[27,255,215],{"class":37},[27,257,258],{"class":53},"}=${",[27,260,100],{"class":166},[27,262,170],{"class":53},[27,264,221],{"class":37},[27,266,267],{"class":53},")",[27,269,270],{"class":53},"}`",[27,272,194],{"class":37},[27,274,276,279,282,285,288,291,294,297],{"class":29,"line":275},10,[27,277,278],{"class":33},"    if",[27,280,281],{"class":37}," (currentIndex ",[27,283,284],{"class":33},"!==",[27,286,287],{"class":37}," entries.",[27,289,290],{"class":66},"length",[27,292,293],{"class":33}," -",[27,295,296],{"class":66}," 1",[27,298,177],{"class":37},[27,300,302,305,308,311,314],{"class":29,"line":301},11,[27,303,304],{"class":37},"      keyValPair ",[27,306,307],{"class":33},"+=",[27,309,310],{"class":53}," \"&\"",[27,312,313],{"class":37},"; ",[27,315,317],{"class":316},"sAwPA","\u002F\u002F PS: Don't want URLs ending with '&' :)\n",[27,319,321],{"class":29,"line":320},12,[27,322,323],{"class":37},"    }\n",[27,325,327,330,332],{"class":29,"line":326},13,[27,328,329],{"class":37},"    query ",[27,331,307],{"class":33},[27,333,334],{"class":37}," keyValPair;\n",[27,336,338],{"class":29,"line":337},14,[27,339,340],{"class":37},"  });\n",[27,342,344,347],{"class":29,"line":343},15,[27,345,346],{"class":33},"  return",[27,348,349],{"class":37}," query;\n",[27,351,353],{"class":29,"line":352},16,[27,354,355],{"class":37},"}\n",[27,357,359],{"class":29,"line":358},17,[27,360,157],{"emptyLinePlaceholder":156},[27,362,364,367],{"class":29,"line":363},18,[27,365,366],{"class":166},"buildQuery",[27,368,369],{"class":37},"(obj);\n",[27,371,373],{"class":29,"line":372},19,[27,374,375],{"class":316},"\u002F\u002F Output: \"name=John%20Doe&age=20\"\n",[10,377,378,379,382],{},"You can implement the same with ",[24,380,381],{},"reduce"," too:",[17,384,386],{"className":19,"code":385,"language":21,"meta":22,"style":22},"function buildQuery(obj) {\n  return Object.entries(obj).reduce(\n    (query, [key, val], currentIndex, entries) => {\n      let keyValPair = query + `${key}=${encodeURIComponent(val)}`;\n      if (currentIndex !== entries.length - 1) {\n        keyValPair += \"&\"; \u002F\u002F PS: Don't want URLs ending with '&' :)\n      }\n      return keyValPair;\n    },\n    \"\"\n  );\n}\n\n\u002F\u002F Output: \"name=John%20Doe&age=20\"\n",[24,387,388,400,416,447,479,498,511,516,523,528,533,538,542,546],{"__ignoreMap":22},[27,389,390,392,394,396,398],{"class":29,"line":30},[27,391,163],{"class":33},[27,393,167],{"class":166},[27,395,170],{"class":37},[27,397,174],{"class":173},[27,399,177],{"class":37},[27,401,402,404,407,409,411,413],{"class":29,"line":47},[27,403,346],{"class":33},[27,405,406],{"class":37}," Object.",[27,408,203],{"class":166},[27,410,206],{"class":37},[27,412,381],{"class":166},[27,414,415],{"class":37},"(\n",[27,417,418,421,424,427,429,431,433,435,437,439,441,443,445],{"class":29,"line":60},[27,419,420],{"class":37},"    (",[27,422,423],{"class":173},"query",[27,425,426],{"class":37},", [",[27,428,215],{"class":173},[27,430,218],{"class":37},[27,432,221],{"class":173},[27,434,224],{"class":37},[27,436,227],{"class":173},[27,438,218],{"class":37},[27,440,203],{"class":173},[27,442,234],{"class":37},[27,444,237],{"class":33},[27,446,44],{"class":37},[27,448,449,452,454,456,458,461,463,465,467,469,471,473,475,477],{"class":29,"line":72},[27,450,451],{"class":33},"      let",[27,453,248],{"class":37},[27,455,41],{"class":33},[27,457,186],{"class":37},[27,459,460],{"class":33},"+",[27,462,253],{"class":53},[27,464,215],{"class":37},[27,466,258],{"class":53},[27,468,100],{"class":166},[27,470,170],{"class":53},[27,472,221],{"class":37},[27,474,267],{"class":53},[27,476,270],{"class":53},[27,478,194],{"class":37},[27,480,481,484,486,488,490,492,494,496],{"class":29,"line":153},[27,482,483],{"class":33},"      if",[27,485,281],{"class":37},[27,487,284],{"class":33},[27,489,287],{"class":37},[27,491,290],{"class":66},[27,493,293],{"class":33},[27,495,296],{"class":66},[27,497,177],{"class":37},[27,499,500,503,505,507,509],{"class":29,"line":160},[27,501,502],{"class":37},"        keyValPair ",[27,504,307],{"class":33},[27,506,310],{"class":53},[27,508,313],{"class":37},[27,510,317],{"class":316},[27,512,513],{"class":29,"line":180},[27,514,515],{"class":37},"      }\n",[27,517,518,521],{"class":29,"line":197},[27,519,520],{"class":33},"      return",[27,522,334],{"class":37},[27,524,525],{"class":29,"line":242},[27,526,527],{"class":37},"    },\n",[27,529,530],{"class":29,"line":275},[27,531,532],{"class":53},"    \"\"\n",[27,534,535],{"class":29,"line":301},[27,536,537],{"class":37},"  );\n",[27,539,540],{"class":29,"line":320},[27,541,355],{"class":37},[27,543,544],{"class":29,"line":326},[27,545,157],{"emptyLinePlaceholder":156},[27,547,548],{"class":29,"line":337},[27,549,375],{"class":316},[10,551,552,553],{},"There are other ways of doing this which are more or less similar. But in my\nopinion, there's a much cleaner way of dealing with this problem. If you haven't\nread the title yet, it is by using ",[24,554,555],{},"URLSearchParams",[17,557,559],{"className":19,"code":558,"language":21,"meta":22,"style":22},"function buildQuery(obj) {\n  let query = new URLSearchParams();\n  Object.entries(obj).forEach(([key, val]) => {\n    query.set(key, val);\n  });\n  return query.toString();\n}\n\n\u002F\u002F Output: \"name=John+Doe&age=20\"\n",[24,560,561,573,590,615,626,630,642,646,650],{"__ignoreMap":22},[27,562,563,565,567,569,571],{"class":29,"line":30},[27,564,163],{"class":33},[27,566,167],{"class":166},[27,568,170],{"class":37},[27,570,174],{"class":173},[27,572,177],{"class":37},[27,574,575,577,579,581,584,587],{"class":29,"line":47},[27,576,183],{"class":33},[27,578,186],{"class":37},[27,580,41],{"class":33},[27,582,583],{"class":33}," new",[27,585,586],{"class":166}," URLSearchParams",[27,588,589],{"class":37},"();\n",[27,591,592,594,596,598,600,602,604,606,608,611,613],{"class":29,"line":60},[27,593,200],{"class":37},[27,595,203],{"class":166},[27,597,206],{"class":37},[27,599,209],{"class":166},[27,601,212],{"class":37},[27,603,215],{"class":173},[27,605,218],{"class":37},[27,607,221],{"class":173},[27,609,610],{"class":37},"]) ",[27,612,237],{"class":33},[27,614,44],{"class":37},[27,616,617,620,623],{"class":29,"line":72},[27,618,619],{"class":37},"    query.",[27,621,622],{"class":166},"set",[27,624,625],{"class":37},"(key, val);\n",[27,627,628],{"class":29,"line":153},[27,629,340],{"class":37},[27,631,632,634,637,640],{"class":29,"line":160},[27,633,346],{"class":33},[27,635,636],{"class":37}," query.",[27,638,639],{"class":166},"toString",[27,641,589],{"class":37},[27,643,644],{"class":29,"line":180},[27,645,355],{"class":37},[27,647,648],{"class":29,"line":197},[27,649,157],{"emptyLinePlaceholder":156},[27,651,652],{"class":29,"line":242},[27,653,654],{"class":316},"\u002F\u002F Output: \"name=John+Doe&age=20\"\n",[10,656,657,658,661,662,665],{},"The ",[24,659,660],{},"set(key,val)"," method in the URLSearchParams class sets\u002Freplaces the key and\nvalue into the query whereas ",[24,663,664],{},"append(key, val)"," appends\u002Fadds the key\u002Fvalue into\nthe query. You can use either of those based on the use case;",[10,667,668],{},"What about the other way round? What if I have a URL and I want to build an\nobject out of the key\u002Fvalues you ask?",[10,670,671,672,674,675,678],{},"Yep, URLSearchParams has you covered. You can initialize the URLSearchParams\nconstructor with a string i.e query params and loop over it using either\n",[24,673,209],{}," loop or the classic ",[24,676,677],{},"for..of"," loop.",[17,680,682],{"className":19,"code":681,"language":21,"meta":22,"style":22},"let query = \"name=John%Doe&age=20\";\n\nfunction buildUser(query) {\n  let params = new URLSearchParams(query);\n  let user = {};\n  params.forEach((val, key) => {\n    user[key] = val;\n  });\n  return user;\n}\n\n\u002F\u002F Output: {name: \"John Doe\", age: \"20\"}\n",[24,683,684,697,701,714,730,741,763,773,777,784,788,792],{"__ignoreMap":22},[27,685,686,688,690,692,695],{"class":29,"line":30},[27,687,34],{"class":33},[27,689,186],{"class":37},[27,691,41],{"class":33},[27,693,694],{"class":53}," \"name=John%Doe&age=20\"",[27,696,194],{"class":37},[27,698,699],{"class":29,"line":47},[27,700,157],{"emptyLinePlaceholder":156},[27,702,703,705,708,710,712],{"class":29,"line":60},[27,704,163],{"class":33},[27,706,707],{"class":166}," buildUser",[27,709,170],{"class":37},[27,711,423],{"class":173},[27,713,177],{"class":37},[27,715,716,718,721,723,725,727],{"class":29,"line":72},[27,717,183],{"class":33},[27,719,720],{"class":37}," params ",[27,722,41],{"class":33},[27,724,583],{"class":33},[27,726,586],{"class":166},[27,728,729],{"class":37},"(query);\n",[27,731,732,734,736,738],{"class":29,"line":153},[27,733,183],{"class":33},[27,735,38],{"class":37},[27,737,41],{"class":33},[27,739,740],{"class":37}," {};\n",[27,742,743,746,748,751,753,755,757,759,761],{"class":29,"line":160},[27,744,745],{"class":37},"  params.",[27,747,209],{"class":166},[27,749,750],{"class":37},"((",[27,752,221],{"class":173},[27,754,218],{"class":37},[27,756,215],{"class":173},[27,758,234],{"class":37},[27,760,237],{"class":33},[27,762,44],{"class":37},[27,764,765,768,770],{"class":29,"line":180},[27,766,767],{"class":37},"    user[key] ",[27,769,41],{"class":33},[27,771,772],{"class":37}," val;\n",[27,774,775],{"class":29,"line":197},[27,776,340],{"class":37},[27,778,779,781],{"class":29,"line":242},[27,780,346],{"class":33},[27,782,783],{"class":37}," user;\n",[27,785,786],{"class":29,"line":275},[27,787,355],{"class":37},[27,789,790],{"class":29,"line":301},[27,791,157],{"emptyLinePlaceholder":156},[27,793,794],{"class":29,"line":320},[27,795,796],{"class":316},"\u002F\u002F Output: {name: \"John Doe\", age: \"20\"}\n",[10,798,799,800,218,803,57,806,809],{},"URLSearchParams also comes with some handy utility functions like ",[24,801,802],{},"has",[24,804,805],{},"get",[24,807,808],{},"values"," etc. I encourage you to look it up and read more about it.",[10,811,812],{},"Further Reading \u002F References:",[814,815,816,826,833],"ul",{},[817,818,819],"li",{},[820,821,825],"a",{"href":822,"rel":823},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FURLSearchParams",[824],"nofollow","URLSearchParams MDN",[817,827,828],{},[820,829,832],{"href":830,"rel":831},"https:\u002F\u002Fgooglechrome.github.io\u002Fsamples\u002Furlsearchparams\u002Findex.html",[824],"Google Chrome Labs",[817,834,835],{},[820,836,839],{"href":837,"rel":838},"https:\u002F\u002Fjakearchibald.com\u002F2021\u002Fencoding-data-for-post-requests\u002F",[824],"Encoding data for POST Request by Jake Archibald",[841,842,843],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}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 pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":22,"searchDepth":47,"depth":47,"links":845},[],"2021-08-20","Build and read query strings with URLSearchParams instead of joining strings by hand. Turn an object into a query, parse one back, and let the browser handle the escaping.",false,"md","2026-08-29T17:42:32+07:00",{},"\u002Fblog\u002Furl-search-params","3 min read",{"title":5,"description":847},"blog\u002Furl-search-params","gHPBStj-vrrH4_UbB83sL70HQCBDvYUem4qqRvrbwpw",1788101292831]