I am trying to make my website SEO friendly with meta tags.
I am implementing server-side rendering in my application. After this, I am getting the following error:
ReferenceError: localStorage is not defined.
Please help how to resolve it.
My package.json
:
{
"main": "server.js",
"scripts": {
"start-dev": "NODE_ENV=development webpack -w & NODE_ENV=development node server.js",
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.18.0",
"express": "^4.15.3",
"firebase": "^4.12.1",
"html2canvas": "^1.0.0-alpha.12",
"react": "^16.2.0",
"react-adsense": "0.0.5",
"react-dom": "^16.2.0",
"react-facebook-login": "^4.0.1",
"react-google-login": "^3.2.1",
"react-meta-tags": "^0.3.0",
"react-router-dom": "^4.2.2",
"react-router-match-as-promised": "^1.0.5",
"react-scripts": "1.1.1",
"react-share": "^2.1.1",
"react-slick": "^0.22.3"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react-app": "^3.1.2",
"babel-preset-stage-0": "^6.24.1",
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^2.1.2",
"file-loader": "^0.11.2",
"postcss-loader": "^2.0.6",
"webpack": "^3.1.0",
"webpack-node-externals": "^1.7.2"
}
}
Meta Tags commonly used in all pages.
Home.js
<code>
import React, { Component } from 'react';
import axinst from '../common';
import {TabBox,TabBox2,TabBox3} from '../common/tabbox';
import Ads from '../common/ads';
import SubscribeFrm from '../common/subscribefrm';
import MetaTags from 'react-meta-tags';
import AdSense from 'react-adsense';
import Loader from '../common/loader';
class Home extends Component {
constructor(props) {
super(props);
}
state = {
header:[],
otherSports:[],
wizztalk:[],
sports:[],
isProgress:'',
activeCat: '',
metaTitle:'',
metaDesc:'',
metaKey:''
}
componentDidMount(){
// axinst.get('/home')
this.setState({isProgress:true});
axinst.get('/home').then(response => {
this.setState({isProgress:false});
const header = response.data.data.Header;
const sports = response.data.data.Sports;
const otherSports = response.data.data.OtherSports;
const wizztalk = response.data.data.Wizztalk;
const metaTitle = response.data.data.metaTitle;
const metaDesc = response.data.data.metaDesc;
const metaKey = response.data.data.metaKeyword;
this.setState({header});
this.setState({sports});
this.setState({otherSports})
this.setState({wizztalk});
this.setState({metaTitle});
this.setState({metaDesc});
this.setState({metaKey});
}).catch(function (error) {
// console.log(error);
// console.log('error');
});
}
render() {
const hD = this.state.header;
const sport = this.state.sports;
return (
<div id="maincontent">
<MetaTags>
<title>{this.state.metaTitle}</title>
<meta name="title" content={this.state.metaTitle} />
<meta name="keywords" content={this.state.metaKeyword} />
<meta name="description" content={this.state.metaDesc} />
<meta name="og:description" content={this.state.metaDesc} />
<meta name="og:title" content={this.state.metaTitle} />
<meta name="og:image" content={process.env.PUBLIC_URL +"/images/logo.png"}/>
</MetaTags>
</code>
Hey y’all.
This is about my first time trying out Next.js. I’m not really much of a coder, just trying to study some stuff out. I’ve set up a dark mode function, following this video right here. At first, it was working normally. But all of the sudden, it started popping up this localStorage error and I don’t know what to do.
I’m working with Tailwind CSS too. This is the function:
import React, { useEffect, useState } from 'react';
export default function DarkModeToggle() {
const [theme, setTheme] = useState(localStorage.theme);
const colorTheme = theme === 'dark' ? 'light' : 'dark';
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove(colorTheme);
root.classList.add(theme);
localStorage.setItem('theme', theme);
}, [theme, colorTheme]);
return [colorTheme, setTheme];
}
Would love some help here.
Thanks a lot.
Hi @danilo-leal. The issue you are seeing is because localStorage
(aka window.localStorage
) is not defined on the server side. Next server renders your components, so when that happens and it tried to access localStorage
it can’t find it. You’ll have to wait until the browser renders it in order to use localStorage
.
For your example, you should just be able to change const [theme, setTheme] = useState(localStorage.theme);
to const [theme, setTheme] = useState(null);
because your useEffect
will run once React renders your component on the client side (useEffect
only uses on the client, not server) and then localStorage
will have the theme
value after that effect runs.
For other use cases …
View full answer
Hi @danilo-leal. The issue you are seeing is because localStorage
(aka window.localStorage
) is not defined on the server side. Next server renders your components, so when that happens and it tried to access localStorage
it can’t find it. You’ll have to wait until the browser renders it in order to use localStorage
.
For your example, you should just be able to change const [theme, setTheme] = useState(localStorage.theme);
to const [theme, setTheme] = useState(null);
because your useEffect
will run once React renders your component on the client side (useEffect
only uses on the client, not server) and then localStorage
will have the theme
value after that effect runs.
For other use cases you might have that use window in the future, you can check
if (typeof window !== ‘undefined’)` which is a good way to check for whether you are on the client vs server.
Or another approach would be to use Next’s dynamic imports with ssr: false
although this is usually only needed for more involved use cases (i.e. if you are importing a chart/graph library or something similar that uses window
).
20 replies
thank you @jamesmosier this code For other use cases you might have that use window in the future, you can check if (typeof window !== 'undefined')` which is a good way to check for whether you are on the client vs server.
worked for me.
I am using appy theme by Cruip which incorporates tailwindCSS new «dark-mode» option.
hey guys!
just coming back to this thread for a bit to share a blog post of mine where I go through how I ended up implementing the dark mode, which made me come here to take some questions by the time I was battling out on how to do it. finally got to a very good design, id like for you to check it out
https://daniloleal.co/my-world/thinking/darkmode-next-tailwind
This is great. I’m glad you were able to figure it out. Kudos!
Ps: I read through and found that and this typo «espeacially»
I used
const [theme, setTheme] = useState(
typeof window !== "undefined" ? localStorage.theme : "light"
);
and some component will show the wrong theme color when refresh the page. Use this answer and everything works perfectly.
This discussion helped me a lot on understanding how localsotrage works in Next js. However i’m having a more specific case.
I’m converting an app which used express into Next. I used if (typeof window !== "undefined")
in useEffect hook but i have this in my useState: const [job, setJob] = useState( localStorage.getItem("job") ? JSON.parse(localStorage.getItem("job")) : null );
and i’m getting ReferenceError: localStorage is not defined
here.
Anyone have any clue how do i fix this?
1 reply
I think it’s the same as the answer above. window.localStorage
will be available after nextjs
rendered your app. That’s why you can’t use localStorage
in useState
because at that stage, it’s on the Next server’s job, which doesn’t have localStorage
.
I used:
const ISSERVER = typeof window === "undefined";
if (!ISSERVER) localStorage.setItem(key, value);
and it worked for me
hope it help you
0 replies
You can use this code snippet.
`if (process.browser) {
if (localStorage != undefined) {
const token = localStorage.getItem(«token»);
if (token != null) {
headers = {
Accept: "application/json",
Authorization: `Bearer ${token}`,
}
}
}
}`
1 reply
what kind of variable is that ‘headers’? Is that inside the configs? Is there any way to put something like that inside the configs? Or any way to do that after getting the token? I mean to set a global header.
this is how I will do it using lazy initialization:******
import React, { useEffect, useState } from ‘react’;
const getInitialTheme =()=>window.localStorage.getItem(‘theme’)
export default function DarkModeToggle() {
const [theme, setTheme] = useState(getInitialTheme);
const colorTheme = theme === ‘dark’ ? ‘light’ : ‘dark’;
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove(colorTheme);
root.classList.add(theme);
localStorage.setItem('theme', theme);
}, [theme, colorTheme]);
return [colorTheme, setTheme];
}
0 replies
In this tutorial we will describe you how to implement local storage without getting any error:
we will show you two way we can solve the local storage error. 1. from server side. 2. from client side.
ERROR ReferenceError: localStorage is not defined
1. From server side
Local store will render at server side by using localstoreage-poyfill library that hold proxy browser support at server end. This way is faster render of you application.
First install the package by node package manager to implement in-memory localStorage to allow at server side.
npm install localstorage-polyfill
Now open the server.ts file and add the code to it.
import 'localstorage-polyfill';
global['localStorage'] = localStorage;
build your project again with npm run build:ssr and serve with npm run serve:ssr.
Hope your all the localStorage errors have been stamp out now. Please give your valuable feedback. If you have any kind of questions or issues about this article, please let me know.
2. From client side
Local store will render at client side until navigation end from browser. Follow the code below. This is lengthy process because wherever you use local storage there you have to you use this process or you may reduce your code by only one place mange your application local storage by service that way you can reduce code.
set, get remove of any localStorage item after Navigation end
This is your component page.
constructor(
private _localStorageService: LocalStorageService ,
private router: Router) {
router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || this.router.url;
this._localStorageService.setData('returnUrl', returnUrl);
}
})
}
This the localStorage service page.
import { Router, NavigationEnd, ActivatedRoute, NavigationStart } from "@angular/router";
.............
...........
@Injectable({
providedIn: 'root'
})
export class LocalStorageService {
setData(setItem,data){
localStorage.setItem(setItem, data);
}
getData(getItem){
return localStorage.getItem(getItem);
}
}
Also, check How to solve window is not defined in angular universal?
Tagged angular localstorage is not defined, angular universal localstorage issue, how to use localstorage with angular universal ssr, localstorage is not defined angular, LocalStorage Is Not Defined In Angular Universal issue, localstorage is not defined javascript, node js localstorage is not defined, referenceerror localstorage is not defined angular universal, ReferenceError: localStorage is not defined