#Client component - useState default value serverside error

164 messages ยท Page 1 of 1 (latest)

gritty forge
#

Hi, ive got an issue with getting serverside error when I am using following syntax inside of my client component which after some explainations makes sense BUT if im getting this error, application is rendering well without any content flashing etc.

Code is simple, there is my state:
const [expanded, setExpanded] = useState<boolean>(window.innerWidth > 768);

Then I have Drawer component which has property expanded where I provide my state.
<Drawer expanded={expanded} ...rest of props>....</Drawer>

Server side error is simple and pointing at window in my useState default state:
ReferenceError: window is not defined

Whenever I am trying to fix server side error with setting expanded in useEffect method it makes my content to move on page render (since expanded is being set after page render). Why does it work if I am getting server error and it does not work if I am fixing the server side error? ๐Ÿ˜„

sterile gorge
#

use null first

gritty forge
#

did, didnt help

sterile gorge
#

const [expanded, setExpanded] = useState<boolean>(false)

gritty forge
#

it will just move all the content after render since it will appear later

#

and also if I set it on true, then it wont work on smaller screens properly

sterile gorge
#

well the clue is window can't be called outside of useEffect so i think we better stick to that no?

#

no, u use both useState and useEffect

#
const [expanded, setExpanded] = useState<boolean>(false)

useEffect(()=>{
  setExpanded(window.innerWidth > 768)
}, [])
gritty forge
#

yeah, but thats what I am saying, the page will render, you will see the content and then it starts moving to right since sider is appearing from left

sterile gorge
#

i see

gritty forge
#

but when its like I provided the page gets rendered without that move

sterile gorge
#

then you load the page first, get the window width BEFORE displaying a data

#

use a context that wait for window.width value

#

at parent level

#

Or doesnt have to be context

gritty forge
#

well, I've done it with isLoading state which would have same effect as anything else that waits for "window" and it works but just adds another delay which is not really necessary

#

will rather keep this error on serverside if its only way to keep everything smooth for end user sad_cry

sterile gorge
#

It will be caught in server but not in client

gritty forge
#

same result (if u were talking about trycatch inside of usestate)

sterile gorge
#

ReferenceError: window is not defined?

#

how did you try catch it

#

how did a try catch not catch the error

gritty forge
#

It did ofc, but you have to return something

sterile gorge
#

no you dont

#

just leave it at catch (e) { }

gritty forge
#

then ur back in circle and drawer is not rendered, then it might be caught by useeffect which will move it again when the page is loaded ๐Ÿ˜„

#

never ending story ๐Ÿ˜„ but I really appreciate ur help

sterile gorge
#

aaaa

#

sry

gritty forge
#

i guess the only "right" solution is to do it with loading screen

sterile gorge
#

just a simple use effect wont hurt right?

right?

#

throw a blank page the user wont notice shh

gritty forge
#

๐Ÿ˜„ I've got full page loader, so I guess I will use it to keep the project without erorrs, I'm not happy with it at all, but atleast it works

#

just for more clarification there is a gif with just useeffect without loading screen

sterile gorge
#

thats decent man

#

it doesnt broke

gritty forge
#

and theres the loading

sterile gorge
#

REE

#

your loading screen is too big

#

beautiful animation though

gritty forge
#

it might be decent if I didnt know that if I just ignore the error then its not happening ๐Ÿ˜„

sterile gorge
#

why not put loading screen here or just use skeletons?

#

why not just use

useEffect(()=>{
  setWindowWidth(window.width)
},[])

at root layout?

gritty forge
#

wont I be forced to mark root layout as client component?

sterile gorge
#

like your provider.tsx

#

it wont mark the rest of your page as client that way, only the client component at root

#

expose ur children in client component, and wrap ur {children} with client component.

gritty forge
#

yeah I understand, I can give it a try

#

gimme sec

#

still the same, component gets undefined first, then it gets the value

sterile gorge
#

yeah ofc thats to be expected

#

just ignore the undefined

#

but the thing is, it loads at first page load (root) so that it wont bugger your sidebar anymore

#

the rest of the flow remain smooth since you already have window at root

gritty forge
#

true

#

300 iq

#

thanks!

#

just realised its same as I had my loading before and it removes all the strings on page from server response (which is making sense) and I dont mind it at this app, but wondering how would I solve this issue if I was developing site where SEO matters peeposhrug

sterile gorge
#

like Home or Account Settings
it always exists regardless of user's state (whether he is in a post or an admin or is under ordering process)

#

then for dynamic data, can do server, can do client depends

gritty forge
#

yeah but since in this case layout stops server rendering then it wont come to the actual page content, but nvm, I guess we spent already a lot of time on this ๐Ÿ˜„

sterile gorge
#

again, misconception about client components, poor it

gritty forge
#

since it wont render the children until client side returns window

sterile gorge
#

it wont render children at client but server already prerenders the children of the client

gritty forge
#

why source code doesnt include "dashboard" text then for example?

sterile gorge
gritty forge
sterile gorge
#

no its not there

gritty forge
#

thats what im saying

sterile gorge
#

you have to work in the Network tabs

#

hmmm

#

makes me think

gritty forge
#

i probably used wrong sentence when I wrote stops SSR but I guess now u got me

sterile gorge
#

u followed this right?

#

damn that page just got longer everyday...

#

last time i went there there wasnt a context section

gritty forge
#

I would say so

sterile gorge
#

i recommend this pattern a lot

gritty forge
#

yeah, but still if ur waiting for clientside to render next children, server cant prerender its content

sterile gorge
#

ok fine it did bug me about window not available in client

sterile gorge
#

ExampleServerComponent (which is under ExampleClientComponent) WILL be prerendered

gritty forge
#

but you are not waiting for anything from clientside there

sterile gorge
sterile gorge
indigo oracle
#

Could you show your code?

gritty forge
#

well maybe I am missing something but as far as I understand what we did window is available only in client not at server, and if I am waiting for window to have actual value to render rest of application then it cannot be prerendered on serverside to return HTML with page content

sterile gorge
#

youre right

#

await for window at client side i guess

gritty forge
#

I think its all about rendering layout mandatory components should be done by css not states

sterile gorge
#

ah

gritty forge
#

and this discussion wouldnt even exist

sterile gorge
#

:')))

gritty forge
#

haha ๐Ÿ˜„

#

I ran to this only cuz I am trying to use existing components

sterile gorge
#

p.s. its not that bad without the loading screen..
as long as it doesnt reopen every soft route change

gritty forge
#

well, you are actually right

#

but im still interested by fact that it worked well with the server error and I literally spent hours trying to make it work same way without having that server side error ๐Ÿ˜„

sterile gorge
#

what if just

#

assume phone layout if window is null

#

xd

gritty forge
#

Would be broken on opposite layout ๐Ÿ˜‚

sterile gorge
#

it wont even go through usestate or useeffect it just checks

#

O(1)

gritty forge
#

If u assume phone layout if its null then the page is loaded as for phone layout And you would have to fix it in useeffect

sterile gorge
#

ok

#

let me give code to better understand what i mean

#

window?.width ? window.width : '0'
if window width doesnt' exist, assume width = 0 which use phone layout
else use that window width

gritty forge
#

If u do window?. u will still get the error, also tried that

#

At server side

#

It didnt make sense to me but its fact

sterile gorge
#

OK

#

im not giving up

#

let widthffs = typeof window !== 'undefined' ? window.width : '0'

gritty forge
#

Then it wont throw error but wont rerender with actual width and you will end up with hidden drawer.. also tried ๐Ÿ˜‚

sterile gorge
#

your browser has window width

#

UGH its the server thingie messing up the window value

#

ughhhhhhhhhhhhhhhhhhhhhhhhhh

gritty forge
#

Yeah

sterile gorge
gritty forge
#

Yeah

sterile gorge
#

reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

sterile gorge
#

css it is ;-;

gritty forge
#

Probably yeah ๐Ÿฅฒ

sterile gorge
#

@gritty forge i know how to solve the windows not defined i think

gritty forge
#

huh? hello ๐Ÿ˜„

sterile gorge
#

use global.window?.

gritty forge
#

mhmm, let me try ^^

sterile gorge
gritty forge
#

seems like it works ๐Ÿ˜ฎ

rancid goblet
gritty forge
#

ur right, app-index.js:32 Warning: Prop style did not match. Server: "background-color:blue" Client: "background-color:red

rancid goblet
#

global.window?.something is just window.something in browser and undefined in the server, they dont match hence the hydration error

#

also @sterile gorge shouldn't it be globalThis?

#

iirc it's not global but globalThis but can't check rn

gritty forge
#

but I was thinking right about that yesterday, I was watching paid course by developedbyed where he was rendering cart based on client side store and he did his "container" with Hydration component which was literally about

const Hydration = ({children}) => {
const [hydration, setHydration] = useState(false)

useEffect(() => { setHydration(true)}, [])

return hydration ? <body>{children}</body> : <body></body>
}

so he pointed out the same way we did it

rancid goblet
#

yeah for things that should only be rendered on the client, that is the way to go

#

hiding the elements before hydration

gritty forge
#

yeah, but how do you solve this if you need to work with SEO? I mean this would remove all the h1's etc., or its no longer a thing?

rancid goblet
#

the reason is that crawlers don't run javascript for you

rancid goblet
sterile gorge
#

i had no hydration error yet

#

but thanks, i will try globalThis

#

im only using window to get current host url, so its nto going to render differently in the server if its undefined

rancid goblet
#

that's good, but keep in mind that if you use that value in the rendering process, you are guaranteed to get hydration errors