From fe545a480dad8375894beff3a49a507ff98d3bb4 Mon Sep 17 00:00:00 2001 From: dwindown Date: Thu, 20 Nov 2025 22:22:40 +0700 Subject: [PATCH] fix: Move useEffect before early returns (Rules of Hooks) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical bug: Hook called after conditional return Problem: - useEffect at line 107 was AFTER early returns (lines 83-102) - When loading/error states triggered early return - Hook order changed between renders - React detected hook order violation - Component broke with blank screen Rules of Hooks violation: ❌ Before: 1. All hooks (useState, useQuery, etc.) 2. Early return if loading 3. Early return if error 4. useEffect (line 107) ← WRONG! After conditional returns ✅ After: 1. All hooks including ALL useEffects 2. Early return if loading 3. Early return if error 4. Render Fix: - Moved useEffect from line 107 to line 62 - Now before any early returns - Changed product?.meta to productQ.data?.meta - Hooks always called in same order - No conditional hook calls Result: ✅ Product edit form loads correctly ✅ No React warnings ✅ Follows Rules of Hooks ✅ Consistent hook order every render --- admin-spa/src/routes/Coupons/index.tsx | 6 ++++-- admin-spa/src/routes/Products/Edit.tsx | 14 +++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/admin-spa/src/routes/Coupons/index.tsx b/admin-spa/src/routes/Coupons/index.tsx index 40ee722..59f4cdd 100644 --- a/admin-spa/src/routes/Coupons/index.tsx +++ b/admin-spa/src/routes/Coupons/index.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import { useNavigate } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { __ } from '@/lib/i18n'; import { CouponsApi, type Coupon } from '@/lib/api/coupons'; import { showErrorToast, showSuccessToast, getPageLoadErrorMessage } from '@/lib/errorHandling'; @@ -253,7 +253,9 @@ export default function CouponsIndex() { /> -
{coupon.code}
+ + {coupon.code} + {coupon.description && (
{coupon.description} diff --git a/admin-spa/src/routes/Products/Edit.tsx b/admin-spa/src/routes/Products/Edit.tsx index f11e2e5..d3a00fd 100644 --- a/admin-spa/src/routes/Products/Edit.tsx +++ b/admin-spa/src/routes/Products/Edit.tsx @@ -59,6 +59,13 @@ export default function ProductEdit() { await updateMutation.mutateAsync(payload); }; + // Sync meta data from product + useEffect(() => { + if (productQ.data?.meta) { + setMetaData(productQ.data.meta); + } + }, [productQ.data?.meta]); + // Set page header with back button and save button useEffect(() => { const actions = ( @@ -103,13 +110,6 @@ export default function ProductEdit() { const product = productQ.data; - // Sync meta data from product - useEffect(() => { - if (product?.meta) { - setMetaData(product.meta); - } - }, [product?.meta]); - return (