{"resource":{"author":{"id":"h2so9H8jPMmgUKGghoNl","name":"Yomesh Gupta","username":"yomeshgupta"},"content":{"link":null,"difficulty":1,"domain":2,"type":1,"isInternal":true,"body":"In this blog post, we are going to see how can we send multiple cookies to the browser in a Remix powered web app.\r\n\r\n## Problem Statement\r\n\r\nLet us consider the `login` functionality in a web app. Once the user is successfully authenticated, we want to --\r\n\r\n1. Redirect users to their respective dashboard\r\n2. Set the session cookie\r\n3. Set the tracking cookie\r\n\r\n## Setting up Session and Redirection\r\n\r\nWe can use Remix's inbuilt utilities to manage the session and redirect.\r\n\r\n```js\r\nimport { createCookieSessionStorage, redirect } from \"remix\";\r\n\r\nconst storage = createCookieSessionStorage({ ... });\r\n\r\nexport async function createUserSession(userId) {\r\n  const session = await storage.getSession();\r\n  session.set(\"userId\", userId);\r\n\r\n  return redirect('/dashboard');\r\n}\r\n```\r\n\r\nIn the function `createUserSession`, we get the session, set the `userId`, and redirect the user to the dashboard route.\r\n\r\n## Setting Cookies\r\n\r\n1. The HTTP helper `redirect` provided by Remix takes an object as the second parameter where we can set different options like `status`, `headers`, and so on. Let us use that to send the `Set-Cookie` header with the session cookie as the value.\r\n\r\n```js\r\n...\r\n\r\nreturn redirect('/dashboard', {\r\n  headers: {\r\n    'Set-Cookie': await storage.commitSession(session)\r\n  }\r\n});\r\n```\r\n\r\nWe are now redirecting the user to the dashboard and also setting the `session` cookie to keep them logged in.\r\n\r\n2. Now, we want to set the tracking cookie. We can try doing the same thing as the session cookie and set another `Set-Cookie` header.\r\n\r\n```js\r\n...\r\n\r\nreturn redirect('/dashboard', {\r\n  headers: {\r\n    'Set-Cookie': await storage.commitSession(session),\r\n    'Set-Cookie': 'user_tracking_id=e8bb43229de9; Max-Age=2592000; Path=/; Secure; SameSite=Lax'\r\n  }\r\n});\r\n```\r\n\r\nHowever, the above code snippet introduces a new problem. The most recent `Set-Cookie` key would overwrite the previous ones.\r\n\r\n## Resolving Same Header Key Issue\r\n\r\nWe can resolve the above-mentioned problem by using the [Headers()](https://developer.mozilla.org/en-US/docs/Web/API/Headers/Headers) constructor. We can create a new instance of the Headers object, append keys to it, and send it to the client.\r\n\r\n```js\r\n...\r\n\r\nconst headers = new Headers();\r\nheaders.append(\"Set-Cookie\", await storage.commitSession(session));\r\nheaders.append('Set-Cookie': 'user_tracking_id=e8bb43229de9; Max-Age=2592000; Path=/; Secure; SameSite=Lax');\r\n\r\nreturn redirect('/dashboard', {\r\n  headers,\r\n});\r\n```\r\n\r\nThis resolves our problem and both cookies would be stored in the user browser! 🙌\r\n\r\nI hope this blog post helped you in some way. Please do share it and show our content much-needed love! 😄\r\n\r\nIf you feel something is missing/wrong/improvement is possible then feel free to reach out -- [Devtools Tech](https://twitter.com/devtoolstech) and [Yomesh Gupta](https://twitter.com/yomeshgupta)\r\n","languages":[],"editorConfig":{}},"stats":{"views":17037,"used":0,"likes":0},"description":"","published":true,"isActive":true,"tags":["","javascript","cookies","remix run","js framework","web fundamentals","frontend","coding","headers","http","redirection","tracking","session"],"slug":"how-to-send-multiple-cookies-in-a-remix-powered-web-app---rid---ndORf220mRIUxvoJPvtb","isPremium":false,"categories":[],"requires":[],"_id":"6206280b1641361c7c65a721","title":"How to Send Multiple Cookies in a Remix Powered Web App?","resourceId":"ndORf220mRIUxvoJPvtb","createdAt":1644570635295,"modifiedAt":1644571041887},"currentUser":null,"isOwner":false,"recommendations":{"questions":[{"_id":"67f7bfc1cd4be7c30c3937c0","content":{"languages":["javascript","typescript"],"difficulty":1},"tags":["javascript"," ui","ux","devtools tech","coding","frontend","code","rippling","frontend coding","interview questions","interview challenge","problem solving"],"slug":"count-total-comments---qid---ZOhP1z8MNP3Jo0RiK5mg","title":"Count Total Comments ","questionId":"ZOhP1z8MNP3Jo0RiK5mg"},{"_id":"639866de22480f26b3caadf2","content":{"languages":["react"],"difficulty":2},"tags":["frontend","code","javascript","react","react custom hooks","coding","programming","frontend interview questions"],"slug":"how-to-create-usewhydidyouupdate-hook-in-react-js-or-javascript-interview-question-or-frontend-problem-solving-or-custom-react-hooks---qid---SueLIwijVoBOzrNJ0Z5E","title":"How to create useWhyDidYouUpdate hook in React.js? | JavaScript Interview Question | Frontend Problem Solving | Custom React Hooks","questionId":"SueLIwijVoBOzrNJ0Z5E"},{"_id":"62fb6d1477f9961d5b7c7df6","content":{"languages":["html","react"],"difficulty":1},"tags":["javascript","html calculator","html css","begineer","frontend begineer","frontend coding challenges","ui","ux","javascript interview questions","devtools tech","frontend masters","learn javascript","practice frontend"],"slug":"build-a-simple-html-calculator-or-frontend-coding-challenge-or-vanilla-javascript-or-machine-coding-round---qid---95l5mqyP6FmG3hVbnj9P","title":"Build a Simple HTML Calculator | Frontend Coding Challenge | Vanilla JavaScript | Machine Coding Round ","questionId":"95l5mqyP6FmG3hVbnj9P"},{"_id":"66228b6d4079503047f670ed","content":{"languages":["react","html"],"difficulty":2},"tags":["javascript","frontend","ui","atlassian","ux","devtools tech","coding","frontend challenge","blog","tutorials","google","trees"],"slug":"how-to-build-a-confluence-like-sidebar-with-tree-structure-or-atlassian-frontend-interview-question-or-react-js---qid---3r7988VsESMQBt9vP1Zi","title":"How to build a Confluence-like Sidebar with Tree Structure? | Atlassian Frontend Interview Question | React.js","questionId":"3r7988VsESMQBt9vP1Zi"},{"_id":"6610e9864e1bed1edc0bc0f5","content":{"languages":["javascript","typescript"],"difficulty":4},"tags":["frontend","array","interview question","problem solving","makemytrip frontend interview question","devtools tech","tutorial","blog"],"slug":"write-a-function-to-return-the-count-of-numbers-in-an-array-or-makemytrip-frontend-interview-question---qid---cjzjsfJUP0zHb2lgPJVy","title":"Write a function to return the count of numbers in an Array | MakeMyTrip Frontend Interview Question","questionId":"cjzjsfJUP0zHb2lgPJVy"}],"resources":[{"_id":"601c195f0858864c592fb52e","content":{"difficulty":2,"domain":2,"type":2},"tags":["Javascript","Interview Questions","Web Development","Frontend"],"slug":"chained-calculator-or-frontend-interview-series-or-puneet-ahuja-or-devtools-tech---rid---ohM3pdtnJDCKDgW5nZOy","title":"Chained Calculator | Frontend Interview Series | Puneet Ahuja | Devtools Tech","resourceId":"ohM3pdtnJDCKDgW5nZOy"},{"_id":"692339ccbf1a48f85e0d1d38","content":{"difficulty":4,"domain":2,"type":2,"isInternal":false,"languages":[]},"tags":[""],"slug":"quick-way-to-fix-uncompressed-javascript/css-files-devtools-trick---rid---bz9xmaeXqGkkZaLgj3tL","title":"Quick way to fix Uncompressed JavaScript/CSS Files (DevTools Trick)","resourceId":"bz9xmaeXqGkkZaLgj3tL"},{"_id":"697b25a8132ce4e954d59b37","content":{"difficulty":1,"domain":2,"type":1,"isInternal":true,"languages":[]},"tags":[""],"slug":"rippling-frontend-interview-experience---rid---n4yp5bZBiParUibIGjEe","title":"Rippling Frontend Interview Experience","resourceId":"n4yp5bZBiParUibIGjEe"},{"_id":"66a4ca5daac82a58634c2bfe","content":{"difficulty":4,"domain":2,"type":1,"isInternal":true,"languages":["undefined"]},"tags":["javascript","frontend","ui","ux","coding","atlassian","frontend coding challenge","feature flags","interactive shape"],"slug":"top-atlassian-frontend-interview-questions-and-process---rid---Bu7bJx9jNVoIsrH71Byb","title":"Top Atlassian Frontend Interview Questions and Process","resourceId":"Bu7bJx9jNVoIsrH71Byb"},{"_id":"5fe98d996d3cda64e470c429","content":{"difficulty":4,"domain":2,"type":2},"tags":["javascript","array","interview questions","frontend","nodejs","inheritance","arrow functions"],"slug":"deeply-nested-array-flat-or-frontend-interview-questions---rid---sTyi2N9I1k6kErptXSUi","title":"Deeply Nested Array Flat | Frontend Interview Questions","resourceId":"sTyi2N9I1k6kErptXSUi"}]}}