Reputation: 409
I am working on a nuxt ssr project and learning it and i really have some questions and a problem.
problem is, whenever someone browse the website, it should check cookies and look for certain keys like user_currency and if there is any value available for that keys then we can use that in fetch hook for api call and if there is no user_currency key available then we should add cookie and then in fetch hook we get that cookie_key and pass it to API.
now whats happening with me is,
on first run, in nuxtserverinit we searched for cookie if there are no key present and we add cookie key there and then in fetch hook, console prints it as undefined. but when i refresh the page then we get the cookie value as i wanted.
just part of the codes as example to explain
i tried to set coookie in created, nuxtserverinit but i am not able to get any clue.
nuxtServerInit({ commit }, { req }) {
const isUserCountry = this.$cookies.get('user_country')
if(isUserCountry === undefined){
this.$cookies.set(`user_country`, "India", {
path: '/',
maxAge: 60 * 60 * 24 * 7,
})
}
}
and in fetch hook in the same first run.
async fetch() {
console.log(this.$cookies.get('user_country'))
//upon first run in fresh browser it prints undefined but after refresh it prints stored value
}
looking for some guidance over here.
middleware code inside midddleware/setcountry.js
export default function ({ app }) {
return new Promise((resolve, reject) => {
const isUserCountry = app.$cookies.get('user_country')
if (isUserCountry === undefined) {
fetch('https://ipinfo.io/json?token=************')
.then((response) => response.json())
.then((jsonResponse) => {
const country = jsonResponse.country
app.$cookies.set(`user_country`, country, {
path: '/',
maxAge: 60 * 60 * 24 * 7,
})
})
}
return resolve(true)
})
}
here is fetch in pages/index.vue
async fetch() {
this.mostFavDests = await fetch(
`${process.env.EXPRESS_API_URL}/dests/favdests?country=${this.$cookies.get('user_country')}`
).then(res => res.json())
}
in nuxt.config.js
module.exports = {
ssr: true
}
in layouts/default.vue
export default {
middleware: ['setcountry']
}
according to lifecycle, we should get cookie value in first run
as per @kissu suggestion
in nuxt.config.js
router: {
middleware: ['setcountry']
}
got this error in console
ERROR Cannot set headers after they are sent to the client 14:58:22
at ServerResponse.setHeader (_http_outgoing.js:561:11)
at p (node_modules/cookie-universal/dist/cookie-universal-common.js:1:1337)
at Object.set (node_modules/cookie-universal/dist/cookie-universal-common.js:1:1774)
at server.js:4614:1186
at processTicksAndRejections (internal/process/task_queues.js:95:5)\
some update,
i think nuxti18n is causing this issue somewhere. because if i visit localhost:3000 it works in first run and if i visit localhost:3000/en-IN it print cookies undefined in first run and after refresh it prints cookies in fetch or asyncdata.
here is my i18n config in nuxt.config.js,
[
'nuxt-i18n',
{
locales: [
{
name: 'Espaneol',
code: 'es-ES',
iso: 'es-ES',
file: 'es.js',
icon: '/flags/es.svg',
},
{
name: 'English',
code: 'en-IN',
iso: 'en-IN',
file: 'en.js',
icon: '/flags/in.svg',
},
{
name: 'English',
code: 'en-US',
iso: 'en-US',
file: 'en.js',
icon: '/flags/us.svg',
},
],
langDir: 'locales/',
lazy: false,
defaultLocale: 'en-IN',
strategy: 'prefix',
detectBrowserLanguage: {
useCookie: true,
cookieKey: 'lang',
alwaysRedirect: true,
fallbackLocale: 'en-IN',
},
vuex: {
moduleName: 'i18n',
mutations: {
setLocale: 'I18N_SET_LOCALE',
setMessages: false,
},
preserveState: false,
},
onLanguageSwitched: (previous, current) => {
if (process.client) {
const DATE = new Date()
DATE.setTime(DATE.getTime() + 365 * 24 * 3600 * 1000)
document.cookie = 'lang=' + current + '; path=/; expires=' + DATE.toUTCString()
}
},
},
],
Upvotes: 2
Views: 9148
Reputation: 537
I had a similar use-case: Set access-token
cookie from the server side on the first load; use the token for subsequent API calls.
Cookies are a concept of browser (its just a key set in header), and not of server. So, when we set cookies through cookies.set()
method, we are just returning Set-Cookie
header in the response. cookie-universal-nuxt
extends cookie-universal
and just does get
, set
functions according to the environment it is running in.
During the 1st ssr load, the fetch
hook is executed even before the cookies is set in the browser. That is also the reason it would work in the refresh (where the cookie is set from the 1st request); or an API request would also work which is triggered from the browser after the 1st load - because the cookie is set at this point in time.
But we can solve this problem through a hack. Setting cookie manually in axios default - if you are using axios. Refer this question.
axios.defaults.headers.common['cookie'] = `access_token=${token};`
As nuxtServerInit
runs only on server, the subsequent client requests will not get affected. :)
Upvotes: 2