(low) ConceptResultMap/FitBounds: нестабильная зависимость bounds перезапускает fitBounds на каждом ре-рендере, сбрасывая ручной zoom/pan #1442

Closed
opened 2026-06-15 05:55:39 +00:00 by bot-backend · 0 comments
Collaborator

Severity: low · Категория: frontend · Файл: frontend/src/components/concept/ConceptResultMap.tsx:44-52, 70

ConceptResultMap.tsx:70 — bounds = ringBounds(parcel.coordinates) вычисляется в теле компонента и возвращает НОВЫЙ массив-литерал minLat,minLon],[maxLat,maxLon (стр.33-36) при каждом рендере. FitBounds (стр.44-52) делает useEffect с deps [map, bounds] и вызывает map.fitBounds. Так как ссылка bounds новая каждый рендер, эффект срабатывает на КАЖДОМ ре-рендере, хотя комментарий обещает «do it imperatively once mounted». Импакт: при переключении вкладок вариантов в ConceptVariantsResult (setActive → ре-рендер VariantPanel → ре-рендер ConceptResultMap, parcel неизменный) fitBounds принудительно отбрасывает ручной зум/панораму пользователя обратно к границам участка. Фикс: мемоизировать bounds (useMemo по parcel.coordinates) или вычислять в самом FitBounds через useMap с deps на стабильный ключ; либо вынести fitBounds в эффект с [map] + сериализованным ключом bounds.

Почему баг: ringBounds (стр.19-37) всегда возвращает свежий [[minLat,minLon],[maxLat,maxLon]]. Даже когда parcel тот же самый объект, идентичность bounds меняется, поэтому зависимость [map, bounds] в useEffect (стр.46-50) каждый раз новая. При переключении вкладок вариантов в ConceptVariantsResult (setActive → ре-рендер VariantPanel → ре-рендер ConceptResultMap, parcel неизменный) эффект перезапускается и принудительно вызывает fitBounds, отбрасывая ручной зум/панораму пользователя обратно к границам участка. Комментарий в коде обещает «do it imperatively once mounted», но фактически это происходит на каждом рендере, а не один раз.

Как чинить: Мемоизировать bounds (useMemo по сериализованным координатам участка) или сделать fit один раз: useEffect с пустым deps и ref-флагом, либо зависеть от стабильного ключа (variantKey/строка координат), а не от свежего массива.


deep-audit «армия ботов 2» · verify+harden, confidence 0.9 · unit U90

**Severity:** low · **Категория:** frontend · **Файл:** `frontend/src/components/concept/ConceptResultMap.tsx:44-52, 70` ConceptResultMap.tsx:70 — bounds = ringBounds(parcel.coordinates) вычисляется в теле компонента и возвращает НОВЫЙ массив-литерал [[minLat,minLon],[maxLat,maxLon]] (стр.33-36) при каждом рендере. FitBounds (стр.44-52) делает useEffect с deps [map, bounds] и вызывает map.fitBounds. Так как ссылка bounds новая каждый рендер, эффект срабатывает на КАЖДОМ ре-рендере, хотя комментарий обещает «do it imperatively once mounted». Импакт: при переключении вкладок вариантов в ConceptVariantsResult (setActive → ре-рендер VariantPanel → ре-рендер ConceptResultMap, parcel неизменный) fitBounds принудительно отбрасывает ручной зум/панораму пользователя обратно к границам участка. Фикс: мемоизировать bounds (useMemo по parcel.coordinates) или вычислять в самом FitBounds через useMap с deps на стабильный ключ; либо вынести fitBounds в эффект с [map] + сериализованным ключом bounds. **Почему баг:** ringBounds (стр.19-37) всегда возвращает свежий `[[minLat,minLon],[maxLat,maxLon]]`. Даже когда parcel тот же самый объект, идентичность bounds меняется, поэтому зависимость [map, bounds] в useEffect (стр.46-50) каждый раз новая. При переключении вкладок вариантов в ConceptVariantsResult (setActive → ре-рендер VariantPanel → ре-рендер ConceptResultMap, parcel неизменный) эффект перезапускается и принудительно вызывает fitBounds, отбрасывая ручной зум/панораму пользователя обратно к границам участка. Комментарий в коде обещает «do it imperatively once mounted», но фактически это происходит на каждом рендере, а не один раз. **Как чинить:** Мемоизировать bounds (useMemo по сериализованным координатам участка) или сделать fit один раз: useEffect с пустым deps и ref-флагом, либо зависеть от стабильного ключа (variantKey/строка координат), а не от свежего массива. --- <sub>deep-audit «армия ботов 2» · verify+harden, confidence 0.9 · unit U90</sub>
bot-backend added the
week ревью 1
label 2026-06-15 05:55:39 +00:00
bot-backend added the
scope/backend
label 2026-06-15 11:02:05 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1442
No description provided.