#see if your still getting a hydration
1 messages ยท Page 1 of 1 (latest)
Hi @proven marsh. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Sorry @proven marsh, I seem to be having a bit of trouble. Don't worry though, I've pinged my supprt and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
to be more specific, the error randomly appears
yeah but is the error gone when you removed that useEffect?
I mean the state wouldn't change, so there wouldn't be a hydration
You have a button though
when you remove use effect and you use that button
does it work as intended
good catch, let me try it out
@wary sable I think it's fine in this case
before the app directory, it's pretty common to saw something like
const [isWindowReady, setWindowReady] = useState(false);
useEffect(() => {
setWindowReady(true);
}, []);
// or
// this is not longer valid in app directory
useState(typeof window !== "undefined")
then how to deal with such case?
it's reasonable because many libs are client only right now isWindowReady && <Whatever component>
they are accessing browser api I believe
I don't think that was ever common?
there is already available ways to see if a window is loaded or not
you mean this is on a server component?
nope
you should be able to use
if (document.readyState === 'complete') {
onPageLoad();
} else {
window.addEventListener('load', onPageLoad);
// Remove the event listener when component unmounts
return () => window.removeEventListener('load', onPageLoad);
}
something like this in a use effect to see if a page has loaded
with onPageLoad() being the function that is called when its loaded
what your doing is not great practice
because A. useEffect has no idea when a page is loaded or not
"use client";
import { useEffect, useState } from "react";
export default function Gallery() {
let [isWindowReady, setIsWindowReady] = useState(false);
useEffect(() => {
setIsWindowReady(true);
}, []);
return (
<div>
{/* ๐ข Works, since AcmeCarousel is used within a Client Component */}
{isWindowReady && <AcmeCarousel />}
</div>
);
}
just for the context
use effect has no clue when a window is ready
you say works in the situation its in a RCC
are u saying whe nu attempt it in a RSC
it doesnt work?
yes
I know
I was asking YOU
you wrote:
{/* :green_circle: Works, since AcmeCarousel is used within a Client Component */}
in your code
this implys it doesnt work in a RSC
lol
let me simply it more
actually the codesandbox
don't get what ur trying to show me
this is not and never will denote if a window is ready or not
if it doesn't as you claim, then what might be the correct pattern?
what I just posted
The reason you were having hydration errors is because you have the state by default to false, and a useEffect to true
meanwhile the server js sends it and thinks its false
but the client says its true
what I had understood so far is that useEffect starts to run when component is mounted
so does it mean mounted is different than the window thing
it could happen before or after
Your primary issue
is the difference between client and server
even though its a client component
I am horrible at explaining this
but since the pure client component cannot be in server, it seems like the hydration error will be unavoidable?
or I must use an action to active it, like a button from the example
its just due to the speed at which it occurs
even though there is no server in client side rendering
there is still how its served to the client via the server
the javascript of it that is
๐ then I guess maybe I should simply wait 0.1s
I thought so
and how fast its ready
Just because its a client component does not mean it doesnt deal with the server at all
the react tree thats given to the client is given by a server
and since what ur doing is changing the state of something before the tree is fully loaded
the inital tree != the tree when everything is loaded
and thus why you get a hydration error
Regardless I don't understand why you need to do this?
For your use case you just have a button that changes the visibility
why do you need to change it to true on useEffect?
is simply because many libs are client side only and it accesses a lot of window apis
it used to be fine because everything is client side by default
but it's no longer the case from the app directory
I am not sure what you mean
every component pre-nextjs13 i.e < 13
pretty much is all using client based stuff
unless your using getServerSidedProps
in app directory, everything is SSR by default
that's why the top has the use client directive
what
no
absolutely no its not
well
actually
nvm
i see what ur saying
it is default YES
but everything pre nextjs13 is client side by default
so having a client side component is literally the same as what you did in < next 13 (12, 11 etc)
I mean those looks trouble some codes I provide is just for app directory, for the old directory, everything is fine
and I don't need to write it that way
this is not a app directory
or nextjs 13 issue at all
you would face these exact same issues
in nextjs 12
Like if you did the thing your trying to do
in a nextjs12 page dir
or even nextjs13 page dir
your going to get the same hydration issues
I don't wanna butt in randomly, but just saying SSR and RSC, while both seem similar, they're not the same
I had that misunderstanding too
And then had to look it up lol
yeah my knowledge on this is not proficient
enough to be able to explain to him why it never would work properly
Same, it's so weird compared to RCCs
I was trying to write some better code to justify the weird code instead of an abstraction one ๐ถ
The explanation about it was that RSCs apparently returns a specially formatted string of code that can be interacted with, while SSR doesn't. SSR returns something like a static page when compared to an RSC. Even then most of it still went over my head, that's the only core distinction I remembered.
Id understand it if the string of code returned from a RSC gets inputed into their SSR render, and thats what SSR returns is the static html
So from the article I read, the issue comes from the distinction of what SSR actually is
There's the common understanding of it, but the term literally means "Server Side Rendering" meaning anything that is rendered on the server falls under the umbrella
yeah I know its rendering the html basically
So in a way RSC is SSR, but just a variation we never really used before
SSR does the entire page of html, while RSC does...well just a single component and allowing that component to play nice with the others on the same page
@wary sable actually I got what you mean, ur right, it wouldn't work in next.12 as well
I'm glad I was able to not help and speak about a completely different topic I barely know anything about
My job is done
but do you might I send u a codesandbox with the issue code, will try to be extreme simple
sure
but somehow involve the ugly thing, I just don't want ppl to, u know, solve code for others
Well he can just comment it out
@wary sable here we go, I try to be explicit and state my reason for that ugly hack
https://codesandbox.io/p/sandbox/vigilant-haslett-5cd6gs?file=%2Fcomponents%2FTroubleComponent.tsx
and be minimal
note that the hydration issue as you said, it's random and really up to the internet speed
which could cause the component failed to render on production
but I clearly can't think of a way to tackle it
can I try something
you can do whatever you want
I just quickly setup the code
I think this issue also appears on other libs sometimes
like chart.js iirc
yes, if I move the environment to local machine and production
the hydration will appear as you sad
so the current code errors on your local machine?
not necessary to have the table just flag && <div />
Why wont it error on the sandbox?
it happen indeterministic
probably it's because the speed is being reasonably slow or fast?
oh
I just realized
the changes I applied
you dont see?
"use client";
import { lazy, useEffect, useState } from "react";
import {
registerPlugin,
BasePlugin,
ContextMenu,
AutoColumnSize,
UndoRedo,
DropdownMenu as TableDropdownMenu,
} from "handsontable/plugins";
// const HotTable = lazy(() => import("@handsontable/react"));
import HotTable from "@handsontable/react";
// the general appoarch is directly run registerPlugin here
// if it's a react project
// in next.js, this will cause error becasue it accesses window api
// and this need to be run before the Table component is ready
registerPlugin(BasePlugin);
registerPlugin(ContextMenu);
registerPlugin(AutoColumnSize);
registerPlugin(TableDropdownMenu);
registerPlugin(UndoRedo);
export default function Gallery() {
let [isRegistered, setIsRegistered] = useState(false);
// as a result
// I run it here and then start to render the table component
// useEffect(() => {
// const initTableConfigs = async () => {
// const {
// registerPlugin,
// ContextMenu,
// AutoColumnSize,
// DropdownMenu,
// BasePlugin,
// UndoRedo,
// } = await import("handsontable/plugins");
// registerPlugin(BasePlugin);
// registerPlugin(ContextMenu);
// registerPlugin(AutoColumnSize);
// registerPlugin(DropdownMenu);
// registerPlugin(UndoRedo);
// // will lead to hydration error randomly
// setIsRegistered(true);
// };
// initTableConfigs();
// }, []);
return (
<div>
{/* {isRegistered && ( */}
<HotTable
data={[
["", "Tesla", "Volvo", "Toyota", "Ford"],
["2019", 10, 11, 12, 13],
["2020", 20, 11, 14, 13],
["2021", 30, 15, 12, 13],
]}
licenseKey="non-commercial-and-evaluation"
/>
{/* )} */}
</div>
);
}
this doesnt seem
to be erroring at all
on the sandbox
how do you access the logs
your not using
what I sent though
Idk what ur lazy loading the HotTable
I literally just followed the npm exaples
oh wait
hmm ohld on
you can right click the table
all plugins is not loaded
anyway, if you don't feel comfortable to continue, feel free to stop, you already help me a lot especially for the hydration part
oh
I fixed it
heres mine
since it wont let me edit urs
nevermind
it was a one-off
it didint show error on recompile
but when i refreshed it did
basically two issues I try to tackle, one is plugin need to be loaded before the table, then it's the log error
if plugin is loaded, you right click the table, the menu is not the browser menu
that's why I have that ugly useEffect with useState thing
I solved both, end up random hydration error
maybe the best way it's to just use the traditionally JavaScript way, basically
const table = new HotTable(); // from its vanilla javascript api
\\ then inject the table into the html
instead of the react way @wary sable
๐ and free both of us
I get no errors on this
This will only register the plugins once the window is loaded (aka navigator is loaded)
and then set a state to true so that the HotTable can be rendered
as I stated before useEffect does not run on when page is loaded
so adding these lines:
if (document.readyState === "complete") {
initTableConfigs();
} else {
window.addEventListener("load", initTableConfigs);
// Remove the event listener when component unmounts
return () => window.removeEventListener("load", initTableConfigs);
}
the first statement checks if it loaded already, if it is then you can normally run the program, but in a situation where the navigator is not loaded in yet
it attaches events to load the plugins once the page is fully loaded
actually the link you have it's still the old code
I think you just need to control and save
I did
then it will automatically generate a new link
yay, I think they are using the same link but will different cache based on our ip
you can just copy paste here
too large
i dont got nitro
or
nvm
wait
this is urs
lol
"use client";
import { lazy, useEffect, useState } from "react";
const HotTable = lazy(() => import("@handsontable/react"));
export default function Gallery() {
let [windowLoaded, setWindowLoaded] = useState(false);
// as a result
// I run it here and then start to render the table component
useEffect(() => {
const initTableConfigs = async () => {
const {
registerPlugin,
ContextMenu,
AutoColumnSize,
DropdownMenu,
BasePlugin,
UndoRedo,
} = await import("handsontable/plugins");
registerPlugin(BasePlugin);
registerPlugin(ContextMenu);
registerPlugin(AutoColumnSize);
registerPlugin(DropdownMenu);
registerPlugin(UndoRedo);
// will lead to hydration error randomly
setWindowLoaded(true);
};
// Check if window is ready
if (document.readyState === "complete") {
initTableConfigs();
} else {
window.addEventListener("load", initTableConfigs);
// Remove the event listener when component unmounts
return () => window.removeEventListener("load", initTableConfigs);
}
}, []);
return (
<div>
{windowLoaded && (
<HotTable
data={[
["", "Tesla", "Volvo", "Toyota", "Ford"],
["2019", 10, 11, 12, 13],
["2020", 20, 11, 14, 13],
["2021", 30, 15, 12, 13],
]}
licenseKey="non-commercial-and-evaluation"
/>
)}
</div>
);
}
You can see if you still get hydration issues on your local env
but you shouldnt
let me try it out
@wary sable unfortunately, random hydration
it's a production build locally
yes
A JavaScript library for building user interfaces
it can be triged by state && <div /> easily
without worrying about all the table thing
maybe there is a bug in the lastest next.js
@chrome maple any help here?
prob not a bug per say
but lots of stuff isnt even built for nextjs13 yet
maybe I should switch back to the regular page directory
let me download the clone from sandbox