{"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":14742,"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":"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":"5eb7d8943f4a621665113a3d","content":{"difficulty":1,"languages":"javascript"},"tags":["node.js","javascript","delete operator","frontend fundamentals","javascript fundamentals","web development"],"title":"Output question based on the delete operator in JavaScript","questionId":"TO3XSXEbx9FW3cbnrfvK","slug":"output-question-based-on-the-delete-operator-in-javascript---qid---TO3XSXEbx9FW3cbnrfvK"},{"_id":"697a002c132ce4e954c67f28","content":{"languages":["react"],"difficulty":2},"tags":["javascript","ui","ux","devtools tech","frontend interview question","hackerrank frontend interview question"],"slug":"spreadsheet-grid---qid---nBrwdTgAJo99lGIYefmC","title":"Spreadsheet Grid","questionId":"nBrwdTgAJo99lGIYefmC"},{"_id":"648b384cd12c1e2402053b07","content":{"languages":["react","html"],"difficulty":1},"tags":["javascript","frontend","react","ui","html","css","frontend coding challenge","razorpay","ui challenges","coding","codedamn","egghead","frontend masters","price calculator"],"slug":"build-a-simple-price-calculator-or-frontend-coding-challenge-or-razorpay-interview-question---qid---2lGvliAvIzreHeVSRfGD","title":"Build a Simple Price Calculator | Frontend Coding Challenge | Razorpay Interview Question","questionId":"2lGvliAvIzreHeVSRfGD"},{"_id":"636df7cebc012474df4d37a6","content":{"languages":["javascript"],"difficulty":1},"tags":["javascript","frontend","coding","devtools tech","interview questions","interview preparation","mcq","programming paradigm","tooling","mdn","js paradigm","programming questions","object serialization"],"slug":"what-is-the-process-in-which-an-object-or-data-structure-is-converted-to-series-of-bytes-for-easy-storage-or-network-transfer---qid---tLrb4Y7cnXaPQu3IJy0X","title":"What is the process in which an object or data structure is converted to series of bytes for easy storage or network transfer?","questionId":"tLrb4Y7cnXaPQu3IJy0X"}],"resources":[{"_id":"652d65f9d5ab2876a4ca215c","content":{"difficulty":4,"domain":2,"type":1,"isInternal":false,"languages":["undefined"]},"tags":["frontend","coding","interview","tooling","web tools","ui","ux","atlan","devtools tech"],"slug":"atlan-interview-experience-frontend-engineer-intern---rid---v5soIECQ4OQQ9S1FFR7n","title":"Atlan Interview Experience: Frontend Engineer Intern","resourceId":"v5soIECQ4OQQ9S1FFR7n"},{"_id":"631050a877f9961d5b7ce988","content":{"difficulty":2,"domain":1,"type":2,"isInternal":false},"tags":["javascript","frontend","react","redux","devtools","tooling","state management"],"slug":"create-your-own-redux-or-part-2-or-createstore-api-or-advanced-frontend---rid---H9EEn90tE3Jag6zCfNkM","title":"Create Your Own Redux | Part 2 | CreateStore API | Advanced Frontend","resourceId":"H9EEn90tE3Jag6zCfNkM"},{"_id":"696a34bc132ce4e954b82594","content":{"difficulty":4,"domain":2,"type":1,"isInternal":true,"languages":[]},"tags":["javascript","ui","ux","devtools tech","coding"],"slug":"uber-frontend-interview-experience-sde-2---rid---dCWHwzvBTfbpsf7QzzqX","title":"Uber Frontend Interview Experience (SDE-2)","resourceId":"dCWHwzvBTfbpsf7QzzqX"},{"_id":"5f1ff867cbec5f7ffc0c2fb6","content":{"difficulty":2,"domain":2,"type":1},"tags":["javascript","frontend","reactjs","profiling","performance","chrome","devtools","advanced frontend"],"slug":"profiling-react-performance-with-react-16-and-chrome-devtools---rid---Oj6vkw9ga5NIqw4266kr","title":"Profiling React performance with React 16 and Chrome Devtools.","resourceId":"Oj6vkw9ga5NIqw4266kr"},{"_id":"69234dfebf1a48f85e0d2584","content":{"difficulty":1,"domain":2,"type":2,"isInternal":false,"languages":[]},"tags":["javascript","large lists","virtualization","frontend","performance","web","frontend system design"],"slug":"how-to-render-large-lists-in-react---rid---TC8vdF4wbZwju6fkLIwO","title":"How to render LARGE lists in React?","resourceId":"TC8vdF4wbZwju6fkLIwO"}]}}