
Date Resolved: April 1, 2026
Affected URL: https://travelagreement.artinvoyage.com/GuestAgreementForm?id=...&token=...
Symptom: Guests visiting the agreement portal saw a completely blank white page. The email verification screen never rendered.
The browser console showed:
Minified React error #310
React error #310 means: "Rendered more hooks than during the previous render."
This is a violation of the Rules of Hooks.
In pages/GuestAgreementForm.jsx, a useEffect hook was placed after multiple early conditional return statements in the component function body.
React requires that all hooks must be called unconditionally, before any return statements. If a hook appears after a return, React may or may not reach it depending on state, causing a different number of hooks to be called on different renders — which crashes the component.
export default function GuestAgreementForm() {
// ... all the useState declarations ...
useEffect(() => { /* fetch agreement */ }, [agreementId]);
useEffect(() => { window.scrollTo(0, 0); }, [step]);
if (loading) return <LoadingSpinner />; // ← early return #1
if (!data) return <NotFoundScreen />; // ← early return #2
if (data?.is_voided) return <VoidedScreen />; // ← early return #3
// ⚠️ THIS WAS THE PROBLEM — useEffect AFTER early returns
useEffect(() => {
if (submitted) {
const timer = setTimeout(() => {
window.location.href = "https://artinvoyage.com";
}, 4000);
return () => clearTimeout(timer);
}
}, [submitted]);
}
On the initial render, loading is true, so the component returned early — before reaching the misplaced useEffect. On subsequent renders (after data loaded), React tried to call that extra hook and threw error #310, crashing the entire component and rendering a blank page.
Moved the misplaced useEffect up in the component, above all conditional return statements:
export default function GuestAgreementForm() {
// ... all useState declarations ...
useEffect(() => { /* fetch agreement */ }, [agreementId]);
useEffect(() => { window.scrollTo(0, 0); }, [step]);
// ✅ FIXED — moved here, before any conditional returns
useEffect(() => {
if (submitted) {
const timer = setTimeout(() => {
window.location.href = "https://artinvoyage.com";
}, 4000);
return () => clearTimeout(timer);
}
}, [submitted]);
// All conditional returns now follow AFTER all hooks
if (loading) return <LoadingSpinner />;
if (!data) return <NotFoundScreen />;
if (data?.is_voided) return <VoidedScreen />;
}
Never place a
useEffect,useState,useRef, or any other React hook after a conditionalreturnstatement.
All hooks must be declared at the top of the component function, before any branching logic or early returns. This is a hard rule enforced by React — violating it causes error #310 and a blank page.
utils/currency.js file (investigated and ruled out)guestAgreement backend function (tested and confirmed working — returns 200)405 errors in the console (harmless Base44 platform-level auth logging calls)