Merge pull request #68 from artslidd/develop

fix: resolve insertBefore DOM reconciliation error in React 19
This commit is contained in:
Arthur Belleville 2026-03-30 23:08:18 +02:00 committed by GitHub
commit 48fc005196
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 26 additions and 21 deletions

View file

@ -62,17 +62,6 @@ export const App = () => {
onSavePreferences={saveConsent}
/>
)}
<style>
{`
@keyframes slide {
0% { transform: translateX(-100vw); }
100% { transform: translateX(100vw); }
}
.animate-slide {
animation: slide 24s linear infinite;
}
`}
</style>
</div>
</Router>
</SessionProvider>

View file

@ -1230,6 +1230,15 @@
animation: scale-bounce 3s ease-in-out infinite;
}
@keyframes slide {
0% { transform: translateX(-100vw); }
100% { transform: translateX(100vw); }
}
.animate-slide {
animation: slide 24s linear infinite;
}
/* Animated Border Light */
@keyframes border-light {
0% {

View file

@ -1,7 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import { useSession } from "@xtablo/shared/contexts/SessionContext";
import { Tables } from "@xtablo/shared/types/database.types";
import React, { useEffect } from "react";
import React, { useEffect, useRef } from "react";
import { createStore, StoreApi, useStore } from "zustand";
import { LoadingSpinner } from "../components/LoadingSpinner";
import { api } from "../lib/api";
@ -101,19 +101,26 @@ export const UserStoreProvider = ({ children }: { children: React.ReactNode }) =
}
}, [user]);
if (isPending && shouldFetchUser) {
return <LoadingSpinner />;
}
// Use a stable store ref to avoid creating a new store on every render.
// Always render the Context.Provider to keep a consistent fiber tree structure —
// switching between `return children` and `return <Provider>{children}</Provider>`
// causes a full fiber tree restructure in React 19 concurrent mode, which triggers
// "insertBefore" DOM reconciliation errors.
const storeRef = useRef<StoreApi<User> | null>(null);
if (!user) {
return children;
if (user) {
if (!storeRef.current) {
storeRef.current = createStore<User>()(() => user);
} else {
storeRef.current.setState(() => user, true);
}
} else {
storeRef.current = null;
}
const store = createStore<User>()(() => user);
return (
<UserStoreContext.Provider value={store as StoreApi<User>}>
{children}
<UserStoreContext.Provider value={storeRef.current}>
{isPending && shouldFetchUser ? <LoadingSpinner /> : children}
</UserStoreContext.Provider>
);
};