react-native-safe-area-context
react-native-safe-area-context copied to clipboard
Turn off all edges?
I would like to be able to pass an empty array to the edges prop of SafeAreaView when I don't want any safe area edges. The use case is a reusable component that on some screens I want it to take into account Safe Area, and other screens already take Safe Area into account and I don't want double padding. So I'd like to pass a prop to my reusable component that can be used like so:
const MyComponent = ({ needsSafeArea }) => {
const edges = [];
if (needsSafeArea) {
edges.push('top');
}
return (<SafeAreaView edges={edges}>
{/* My cool component */}
</SafeAreaView>);
};
This code currently results in all edges being activated when needsSafeArea is false. If there's a better way to handle my use case then please let me know.
If you don't need any edges, can you use a View
instead?
const MyComponent = ({ needsSafeArea }) => {
if (needsSafeArea) {
return (
<SafeAreaView edges={['top']}>
{/* My cool component */}
</SafeAreaView>
);
}
return (
<View>
{/* My cool component */}
</View>
);
};
Yes this is a workaround, but not great because you either have to duplicate the code inside or create another layer of abstraction by factoring out the common code into yet another component. It would be much more readable and maintainable to just keep the SafeAreaView structure in place and control the behavior by props.
An empty edges array seemed intuitive to indicate no edges at first (before I re-read the docs), but probably it would be less disruptive to existing code if an optional flag was added called something like 'disabled'.
I've also come to few use cases where I'd use that passing edges={[]}
turns off all edges. It's surprising to me it doesn't, because the code clearly says what I want and that is to use no edges.
If it would work like that and you would have opposite condition like "if something is true, I want only top
edge, otherwise use default edges" you could still do that by edges={condition? ['top'] : undefined}
, so to me it seems like win-win.
Anyway, best workaround I found is to use useSafeAreaInsets
import React from 'react';
import { View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const MyComponent = ({ needsSafeArea }) => {
const { top } = useSafeAreaInsets();
return (
<View style={{paddingTop: needsSafeArea? top : 0}}>
{/* My cool component */}
</View>
);
};
Any news on modifying the bit mask to allow this behaviour? I confirm this would be useful to programmatically change edges while keeping the cool SafeAreaView and not the insets
useSafeAreaInsets
isn't the best solution because it can cause layout flickering (which happens quite commonly in my experience, especially on android). Would really like it if we could pass empty array.
The best work around IMO is to use conditional rendering and contain the SafeAreaView within the regular view.
<View>
{topInsets &&
<SafeAreaView edges={['top']}/>
}
{bottomInsets &&
<SafeAreaView edges={['bottom']}/>
}
</View>
I also vote for this dev-friendly feature!
Yeah, this is an odd one. The default is all edges seen here. You could change this to 0
to mean no edges - then you'd need to update this to default to passing in all edges if the edges
prop isn't provided
Is this planned on the roadmap? Or could we help by creating a PR?
If someone raised a PR for this, we'd merge it. I think it literally is as simple as changing the line I highlighted from RNCSafeAreaViewEdgesAll
to 0
The edges get set to their default here
Would setting that to 0 not change the default to no edges? I think it should still default to all edges, just when passing an empty array, it should use no edges?
@jacobp100 , I've implemented it for iOS, not sure if android needs to be looked at as well, I couldn't find a device to test it on
https://github.com/th3rdwave/react-native-safe-area-context/pull/378