next.js
next.js copied to clipboard
Unable to stop AppContext(Context API) from rendering server side | Local Storage not defined or ClassNames are different client and server side
Link to the code that reproduces this issue
https://github.com/krishnaacharyaa/nextjs-explore
To Reproduce
- Clone & Fork the project
- npm install
- npm run dev
- ReferenceError: localStorage is not defined at getSavedData (./context/appContext.tsx:27:13) at AppContextProvider (./context/appContext.tsx:50:79)
Though it is taken care by wrapping it in (typeof window != undefined) , still the server throws error undefined and even if i have managed it somehow, It throws error saying cilent side and server side css are different.
Though the client side everything is fine and the data is fetched from the localstorage eventually, How to get away with this error? How do I stop this context from rendering in the server side? And what is the correct way of handling this error.
I am open to all the reponses.
Current vs. Expected behavior
I do not expect the server to throw error localstorage is not defined. because at the end of the day it is able to fetch data from the localstorage.
And even after wrapping it in (window!=undefined) it is throwing the error
Provide environment information
Operating System:
Platform: win32
Arch: x64
Version: Windows 11 Enterprise
Binaries:
Node: 20.11.0
npm: N/A
Yarn: N/A
pnpm: N/A
Relevant Packages:
next: 14.1.0
eslint-config-next: 14.1.0
react: 18.2.0
react-dom: 18.2.0
typescript: 5.3.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
App Router, Data fetching (gS(S)P, getInitialProps)
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
No response
Hi,
You have this line:
const [items, setItems] = useState(getSavedData() || initialData || []);
JavaScript works with Applicative Order, so getSavedData() is called.
Internally that functions does this check:
const getSavedData = () => {
var savedData = null;
if (typeof window != undefined) {
savedData = localStorage.getItem(STORE_SELECTION)
? JSON.parse(localStorage.getItem(STORE_SELECTION))
: null;
return savedData;
}
return savedData;
};
Never mind the usage of var, let's look at this if branch:
if (typeof window != undefined) {
That's not the check you want!
Welcome to Node.js v18.18.0.
Type ".help" for more information.
> typeof window != undefined
true
As you can see, in Node, this if branch does run. You want something like if (typeof window !== 'undefined'), because the typeof operator returns a string.
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
You also have this:
- https://github.com/krishnaacharyaa/nextjs-explore/blob/main/app/page.tsx#L7
That won't fly when you try to build the application. Please refer to these documentation entries, where this issue has been expanded upon:
- https://nextjs-faq.com/fetch-api-in-rsc
- https://nextjs-faq.com/fetch-api-in-getserversideprops
Thank you bunch @icyJoseph for your valuable time and the useful links.
I solved the issue by using next/dynamic and giving option ssr: false for the AppContextProvider
https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading#importing-client-components
Can I kindly draw your attention to https://github.com/vercel/next.js/issues/61482
Hi, yeah I just answered there.
Please don't forget to close the issue, if you think it is resolved.
Yeah sure, Thank you @icyJoseph for your answer and time, much appreciated
This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.