feat(F-063): completed feature
This commit is contained in:
@@ -78,13 +78,28 @@ export function ProductEditor({ productId }: ProductEditorProps) {
|
||||
const snapRef = useRef('');
|
||||
const dirtyRef = useRef(false);
|
||||
|
||||
/**
|
||||
* Returns a stable JSON snapshot of the form. The function is a `useCallback`
|
||||
* so the dirty-check effect can safely depend on its identity without
|
||||
* causing a feedback loop with the load effect. Previously `getSnap` was
|
||||
* also in the load effect's dependency list, which (combined with React
|
||||
* state updates inside the load handler) caused the load effect to re-fire
|
||||
* on every render — a fetch loop that broke checkbox selection.
|
||||
*/
|
||||
const getSnap = useCallback(() => JSON.stringify({
|
||||
name, slug, desc, brandId, categoryIds, channels, featured, attributes, state, seoTitle, seoDesc,
|
||||
}), [name, slug, desc, brandId, categoryIds, channels, featured, attributes, state, seoTitle, seoDesc]);
|
||||
|
||||
// Keep a ref to the latest getSnap so the load effect (which uses an empty
|
||||
// deps list to avoid the loop) can still compute the initial snapshot.
|
||||
const getSnapRef = useRef(getSnap);
|
||||
useEffect(() => { getSnapRef.current = getSnap; }, [getSnap]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!productId) { setLoading(false); return; }
|
||||
let cancelled = false;
|
||||
productsApi.get(productId).then((p: Product) => {
|
||||
if (cancelled) return;
|
||||
setName(p.name); setSlug(p.slug); setDesc(p.description ?? '');
|
||||
setBrandId(p.brandId ?? ''); setCategoryIds(p.categoryIds ?? []);
|
||||
setChannels((p as any).channels ?? 'all');
|
||||
@@ -93,10 +108,15 @@ export function ProductEditor({ productId }: ProductEditorProps) {
|
||||
setState(p.state);
|
||||
setSeoTitle((p as any).seoTitle ?? ''); setSeoTitleManual(true);
|
||||
setSeoDesc((p as any).seoDescription ?? ''); setSeoDescManual(true);
|
||||
snapRef.current = getSnap();
|
||||
snapRef.current = getSnapRef.current();
|
||||
setLoading(false);
|
||||
}).catch(() => { setError('No se pudo cargar el producto'); setLoading(false); });
|
||||
}, [productId, getSnap]);
|
||||
}).catch(() => {
|
||||
if (cancelled) return;
|
||||
setError('No se pudo cargar el producto'); setLoading(false);
|
||||
});
|
||||
return () => { cancelled = true; };
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- load effect runs once per productId
|
||||
}, [productId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loading) return;
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 675 B |
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 675 B |
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
Reference in New Issue
Block a user