Repository navigation
fix(ios): keep setEdgeInsets insets when other props change - #100
Conversation
updateProps compared the edgeInsets prop with _edgeInsets, which the setEdgeInsets command also writes. Fabric copies unchanged props from the previous props, so any unrelated prop update (theme, mapType, userLocationEnabled, ...) carried the old edgeInsets value and re-applied it, instantly undoing insets set by the command. Track the last applied prop in _edgeInsetsProp and apply the prop only when it changes. Reset both values in prepareForRecycle so a recycled view does not inherit the previous map's insets.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
- iOS: apply prop changes through setEdgeInsets (duration 0) so a running Apple inset animation stops; drop unused _oldEdgeInsets - iOS Apple: start from in-flight insets when interrupting an animation - iOS static: staticKey change restores prop insets - web: compare edgeInsets prop with last prop, not command-written insets - docs + skill: document prop vs setEdgeInsets precedence
|
Thanks @erickreutz. The core fix works. I reproduced the original bug on The review found three more cases, all reproduced, and I pushed fixes in 2a98b4c. 1. iOS (Apple): a prop change during an animated The prop path called the two-argument
2. Web has the same bug The effect compared the prop with
3. iOS static maps: command insets carry over to the next item after Before this PR, the stale prop re-apply reset the insets as a side effect. Now they stay, so a reused list row rendered (and cached) the new item with the previous item's insets.
Changes in 2a98b4c
Verified: typecheck, lint, tests, prettier and clang-format pass. All cases above were re-run on the iOS sim and in Chrome. Android was not tested. Not fixed here: on web, changing |
On iOS, insets set with the
setEdgeInsetsref method reset whenever any otherMapViewprop changes, such astheme,mapType,userLocationEnabled, orinitialCoordinate. The map snaps back to theedgeInsetsprop instantly, with no animation and no camera refit, so content framed above a bottom sheet or below a header slides under it. Common triggers are a system theme change and location permission arriving after the insets were set. We hit it in the Lugg consumer app, where a light/dark switch pushed route pins behind the status bar. Android is not affected because its prop setters only run for changed keys.The cause is in
-[LuggMapView updateProps:oldProps:]. It compared the incomingedgeInsetsprop with_edgeInsets, which thesetEdgeInsetscommand also writes. Fabric builds each new props object from the previous one, andconvertRawPropkeepssourceProps.edgeInsetsfor keys that did not change, so every unrelated update carries the oldedgeInsetsvalue. Once the command moved_edgeInsetsaway from that value, each update looked like anedgeInsetschange and re-applied the stale prop through the provider's two-argumentsetEdgeInsets:oldEdgeInsets:, which applies with no duration.The fix keeps the last applied prop in
_edgeInsetsPropand applies the prop only when that value changes. The last write still wins: a newedgeInsetsvalue replaces insets set by the command, and a later command replaces the prop.prepareForRecycleresets_edgeInsetsand_edgeInsetsPropto zero, matchinginitWithFrame. Without that reset, a recycled view would keep the previous map's command-set insets whenever its new prop matched the old one. React Native keeps_propsacross recycling, so diffing for the other props is unchanged.Reproduced in the bare example on an iOS 26.5 simulator with Apple Maps: the Home screen sets the bottom inset from the control sheet with
setEdgeInsets, and switching the map type shifted the map down by half the sheet height and moved the Apple attribution behind the sheet. With this change the map stays put. Hiding the map and then opening Static Maps confirms the recycled view does not inherit the inset.