Chander Shoor
Chander Shoor

Reputation: 716

React - “localStorage is not defined” error showing

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>

Upvotes: 70

Views: 184321

Answers (7)

Ashish gautam
Ashish gautam

Reputation: 11

I faced this issue with NextJs while checking the query param values for session creation.

The best working solution was :

if (typeof window !== 'undefined') {
    console.log('Currently on Client side')
} else {
    console.log('Currently on Server Side');
}

Inside of the first check (Client side), simply put all the code to handle localStorage. This works for me fine.

Upvotes: 0

Munira Akter
Munira Akter

Reputation: 61

On Component you can use useEffect hook for waiting the full page load.

    useEffect(() => {
      localStorage.getItem('key');
    }, [input]);

And for hooks or functions you can use if condition to check window is loaded or not like this -

    if(window !== 'undefined'){ 
      localStorage.getItem('key')
    }

Upvotes: 3

Hrittik Bhattacharjee
Hrittik Bhattacharjee

Reputation: 21

This is a more reliable approach if the component logic absolutely depends on the value of lsVar to conditionally render something.

    const Component = () => {
        if (typeof window === "undefined") return null;

        const lsVar = localStorage.getItem("lsVar");

        // component logic
        
        return (<></>);
    }

Upvotes: 0

Shane Sepac
Shane Sepac

Reputation: 826

In my case I used a useEffect to wait for the page to load before using localStorage.

Upvotes: 1

This oneliner did it for me:

const checkout = typeof window !== 'undefined' ? localStorage.getItem('checkout') : null

Upvotes: 21

Sasha
Sasha

Reputation: 5944

You can add a polyfill to your app. I.e. somewhere in your index.js:

if (!window) {
    require('localstorage-polyfill');
}

Upvotes: 4

Patrick Hund
Patrick Hund

Reputation: 20256

When you're rendering on the server, you do not have a browser and thus you do not have access to all the APIs that the browser provides, including localStorage.

In JavaScript code that is running both on the server and on the client (browser), it is common practice to guard against with an if clause that checks if window is defined. “Window” is the root object provided by the browser for all the APIs that are provided by the browser.

Example:

if (typeof window !== 'undefined') {
    console.log('we are running on the client')
} else {
    console.log('we are running on the server');
}

In your case, you want to put your call to localStorage in such an if clause, for example:

if (typeof window !== 'undefined') {
    localStorage.setItem('myCat', 'Tom');
}

Upvotes: 97

Related Questions