fix: resolve infinite loop in useEffect/useCallback hooks

- useProdutos: replaced useCallback([currentPage]) with useRef + useCallback([])
- useEntregas: same fix for listarEntregas
- produtos/page: removed unstable listarProdutos from useEffect deps
- entregas/page: removed unstable listarEntregas from useEffect deps

Root cause: useCallback depended on currentPage but setCurrentPage inside caused circular dependency.
This commit is contained in:
Tiago Yamamoto 2026-03-04 20:57:00 -06:00
parent 11c93ae584
commit b0ffceefa8
4 changed files with 32 additions and 17 deletions

View file

@ -32,6 +32,7 @@ const statusIcons = {
};
function EntregasContent() {
console.log('[ENTREGAS] 🔄 Component render');
const router = useRouter();
const [user, setUser] = useState<any>(null);
const [filtroStatus, setFiltroStatus] = useState<string>("todos");
@ -55,6 +56,7 @@ function EntregasContent() {
// Verificação de autenticação
useEffect(() => {
console.log('[ENTREGAS] 🔑 Auth useEffect triggered');
const checkAuth = async () => {
try {
const storedToken = localStorage.getItem('access_token');
@ -96,7 +98,9 @@ function EntregasContent() {
// Carregar entregas quando usuário for autenticado
useEffect(() => {
console.log('[ENTREGAS] 📦 Data fetch useEffect triggered', { user: !!user, userLoading });
if (user && !userLoading) {
console.log('[ENTREGAS] 📦 Calling listarEntregas...');
listarEntregas({
page: 1,
search: termoBusca.trim() || undefined,
@ -106,7 +110,8 @@ function EntregasContent() {
console.error("❌ Erro ao carregar entregas:", error);
});
}
}, [user, userLoading, listarEntregas]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user, userLoading]);
const handleSearch = async () => {
limparErro();
@ -697,6 +702,9 @@ function EntregasContent() {
);
}
export default function EntregasPage() {
const EntregasPage = () => {
console.log('[ENTREGAS] 🔄 Component render');
return <EntregasContent />;
}
export default EntregasPage;

View file

@ -10,6 +10,7 @@ import ProdutoList from '@/components/ProdutoList';
import { useProdutos, ProdutoFormData } from '@/hooks/useProdutos';
const GestaoProdutos = () => {
console.log('[PRODUTOS] 🔄 Component render');
const router = useRouter();
const [user, setUser] = useState<Models.User<Models.Preferences> | null>(null);
const [editing, setEditing] = useState<Models.Document | null>(null);
@ -45,7 +46,8 @@ const GestaoProdutos = () => {
};
initializeUser();
}, [activeTab, router, listarProdutos]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeTab]);
const handleFormSubmit = async (formData: ProdutoFormData): Promise<boolean> => {
if (editing) {

View file

@ -1,4 +1,4 @@
import { useState, useCallback } from 'react';
import { useState, useCallback, useRef } from 'react';
import { entregasApiService, EntregaBff, EntregasBffParams } from '@/services/entregasApiService';
export interface UseEntregasReturn {
@ -32,6 +32,8 @@ export const useEntregas = (): UseEntregasReturn => {
const [totalEntregas, setTotalEntregas] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
const currentPageRef = useRef(currentPage);
currentPageRef.current = currentPage;
const listarEntregas = useCallback(async (params: EntregasBffParams = {}) => {
setLoading(true);
@ -40,7 +42,7 @@ export const useEntregas = (): UseEntregasReturn => {
try {
// Usar parâmetros fornecidos ou valores padrão
const requestParams = {
page: params.page || currentPage,
page: params.page || currentPageRef.current,
limit: params.limit || DEFAULT_PAGE_SIZE,
search: params.search,
status: params.status,
@ -67,7 +69,7 @@ export const useEntregas = (): UseEntregasReturn => {
} finally {
setLoading(false);
}
}, [currentPage]);
}, []);
const buscarEntregaPorId = useCallback(async (id: string): Promise<EntregaBff | null> => {
try {

View file

@ -1,4 +1,4 @@
import { useState, useCallback } from 'react';
import { useState, useCallback, useRef } from 'react';
import { Models } from 'appwrite';
import { produtoService, ProdutoData } from '@/services/produtoService';
@ -30,18 +30,21 @@ export const useProdutos = (): UseProdutosReturn => {
const [error, setError] = useState<string | null>(null);
const [totalProdutos, setTotalProdutos] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
const currentPageRef = useRef(currentPage);
currentPageRef.current = currentPage;
const listarProdutos = useCallback(async (page = currentPage) => {
const listarProdutos = useCallback(async (page?: number) => {
const targetPage = page ?? currentPageRef.current;
setLoading(true);
setError(null);
try {
const response = await produtoService.listar(page, PAGE_SIZE);
const response = await produtoService.listar(targetPage, PAGE_SIZE);
if (response.success) {
setProdutos(response.documents || []);
setTotalProdutos(response.total || 0);
setCurrentPage(page);
setCurrentPage(targetPage);
} else {
setError(response.error || 'Erro ao carregar produtos');
}
@ -50,7 +53,7 @@ export const useProdutos = (): UseProdutosReturn => {
} finally {
setLoading(false);
}
}, [currentPage]);
}, []);
const cadastrarProduto = useCallback(async (formData: ProdutoFormData): Promise<boolean> => {
setLoading(true);
@ -60,7 +63,7 @@ export const useProdutos = (): UseProdutosReturn => {
const response = await produtoService.criar(formData);
if (response.success) {
await listarProdutos(currentPage);
await listarProdutos(currentPageRef.current);
return true;
} else {
setError(response.error || 'Erro ao cadastrar produto');
@ -72,7 +75,7 @@ export const useProdutos = (): UseProdutosReturn => {
} finally {
setLoading(false);
}
}, [currentPage, listarProdutos]);
}, [listarProdutos]);
const atualizarProduto = useCallback(async (id: string, formData: ProdutoFormData): Promise<boolean> => {
setLoading(true);
@ -82,7 +85,7 @@ export const useProdutos = (): UseProdutosReturn => {
const response = await produtoService.atualizar(id, formData);
if (response.success) {
await listarProdutos(currentPage);
await listarProdutos(currentPageRef.current);
return true;
} else {
setError(response.error || 'Erro ao atualizar produto');
@ -94,7 +97,7 @@ export const useProdutos = (): UseProdutosReturn => {
} finally {
setLoading(false);
}
}, [currentPage, listarProdutos]);
}, [listarProdutos]);
const deletarProduto = useCallback(async (id: string): Promise<boolean> => {
setLoading(true);
@ -104,7 +107,7 @@ export const useProdutos = (): UseProdutosReturn => {
const response = await produtoService.deletar(id);
if (response.success) {
await listarProdutos(currentPage);
await listarProdutos(currentPageRef.current);
return true;
} else {
setError(response.error || 'Erro ao deletar produto');
@ -116,7 +119,7 @@ export const useProdutos = (): UseProdutosReturn => {
} finally {
setLoading(false);
}
}, [currentPage, listarProdutos]);
}, [listarProdutos]);
return {
produtos,