feat(web): add unstable_disableViewOnWeb to SafeAreaProvider - #750
Open
giaBaoJS wants to merge 1 commit into
Open
feat(web): add unstable_disableViewOnWeb to SafeAreaProvider#750giaBaoJS wants to merge 1 commit into
giaBaoJS wants to merge 1 commit into
Conversation
On web the provider always renders a wrapping View, which is not always wanted, for example when the provider is mounted at the root of an app by ExpoRoot. Add an undocumented, unstable opt out that renders children directly instead. Since there is no view to measure when the wrapper is gone, insets and frame fall back to window values, which is the existing behaviour of the branch that runs when the provider element cannot be measured. The prop is web only. The default path and every other platform are unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #637
Context
On web
SafeAreaProvideralways renders a wrappingView, which consumers don't always want — #637 ran into this becauseExpoRootmounts the provider at the root of the app.@satya164 pointed out that switching to a fragment unconditionally is not safe:
and @janicduplessis settled the API:
So this PR is exactly that prop and nothing else: opt-in, undocumented, web-only.
Change
src/NativeSafeAreaProvider.web.tsx:111returns<>{children}</>instead of theViewwhenunstable_disableViewOnWebis set. The prop is declared onNativeSafeAreaProviderPropsandSafeAreaProviderProps; both of those additions are type-only and compile away.No README or docs entry, per "undocumented". There are no other
unstable_props in the repo, so there was no existing convention to follow.Behaviour worth your call
Since #737 the web provider measures its own
Viewto report the frame and to clamp insets. With the wrapper gone there is nothing to measure, so metrics fall back to the window. That is not new code — it is the existingcanMeasureProviderElement === falsepath (src/NativeSafeAreaProvider.web.tsx:33-36, fallback values at:51-57), already exercised by the "falls back to window metrics when ResizeObserver is not available" test. For the root-provider case in the issue, window metrics are the right answer anyway.I deliberately did not try to preserve per-view measurement without a view — that would need a different design (e.g. measuring the parent element) and is more than an unstable escape hatch should carry.
styleis likewise ignored when the prop is set, since there is no element to apply it to. Both are called out in the prop's doc comment.The diff stays out of the measurement effect entirely (only the props destructure and the return statement change), so it should compose cleanly with anything else in flight in that file.
Tests
Four tests added to the existing jsdom suite in
src/__tests__/NativeSafeAreaProvider.web-test.tsx:wraps children in a view by default— asserts the rendered DOM is<div><span id="child"></span></div>, i.e. the wrapper is still there when the prop is not set.renders children without a wrapping element when enabled— asserts the DOM is<span id="child"></span>, no wrapper.reports window insets and frame when enabled— withgetBoundingClientRectmocked to a small rect, metrics still come out as the window insets/frame, proving the fallback path is taken rather than something else being measured.keeps reporting window metrics on resize when enabled— insets and frame still update onresizewith the wrapper gone.The second and third together cover the user-visible claim: no wrapper element in the DOM, and insets still resolve.
Verification
yarn validate:jest: 4 suites, 25 tests, 11 snapshots — green (baseline was 21 tests, 11 snapshots).src/__tests__/__snapshots__/is untouched in this diff, so the native render path (RNCSafeAreaProvider) produces exactly the same tree as before.src/NativeSafeAreaProvider.web.tsxand re-running the suite fails the three "when enabled" tests and passes the default-behaviour one, as expected.yarn prepare, the only emitted runtime JS containingunstable_disableViewOnWebislib/{module,commonjs}/NativeSafeAreaProvider.web.js. CompiledSafeAreaContext.jscontains zero references — the interface addition is erased.ios/,android/,common/,src/specs/,NativeSafeAreaProvider.tsxandNativeSafeAreaProvider.windows.tsxare all unchanged.yarn validate:eslint(0 errors),yarn validate:typescriptandyarn format:prettier:checkall pass.Known risk
You mentioned re-evaluating this in the next major. If a major is close, feel free to park this — it's deliberately small and self-contained so it costs nothing to defer or drop.