facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
119.18k stars 24.32k forks source link

New in RN 0.54, Android only: using display: none and position: absolute together doesn't work right #18415

Closed aarondail closed 1 year ago

aarondail commented 6 years ago

Basically, if you use the styles display: none and position: absolute on a component the component will still be rendered. On Android. iOS works ok. This used to be fine (at least as of 0.52.2).

Environment

Environment:
  OS: macOS Sierra 10.12.6
  Node: 9.8.0
  Yarn: 1.5.1
  npm: 5.6.0
  Watchman: 4.5.0
  Xcode: Xcode 9.2 Build version 9C40b
  Android Studio: 2.3 AI-162.3934792

Packages: (wanted => installed)
  react: ^16.3.0-alpha.1 => 16.3.0-alpha.2
  react-native: 0.54.2 => 0.54.2

Expected Behavior

A component with style display: none should never be rendered.

Here is an example of a component using both styles:

        <View style={{
          position: 'absolute',
          display: 'none',
          bottom: 100,
          left: -30,
          backgroundColor: 'blue',
          borderColor: 'red',
          borderWidth: 9,
        }}>
          <Text> Hey Hey Hey Hey Hey </Text>
        </View>

If I add that to my App.js, and run it, this is what it looks like on iOS:

ios_display_none

I.e. its not rendered, as expected :)

Actual Behavior

This is the same code as above, just running on Android. Note that the element is visible (and actually left: -30 is also not working)

android_display_none

Steps to Reproduce

Create a sample app using react-native init

Paste this into the App.js file, inside the render() method, before the final </View> (for me between lines 35 and 36):

        <View style={{
          position: 'absolute',
          display: 'none',
          bottom: 100,
          left: -30,
          backgroundColor: 'blue',
          borderColor: 'red',
          borderWidth: 9,
        }}>
          <Text> Hey Hey Hey Hey Hey </Text>
        </View>

Run it on iOS. Observe the View is not rendered. Run it on Android. Observe that it is.

tsaohucn commented 6 years ago

me Too

henrikland commented 6 years ago

Same issue here, completely breaks the app I am working on. Will have to find a workaround until this is fixed.

fallenner commented 6 years ago

the issue still exist in RN 0.55.

VijayLogitech commented 6 years ago

display:none, and position:absolute, occupies the corners of the device screen, instead of hiding the native controls. RN 0.54

forkbomb commented 6 years ago

<View style={{position: 'absolute'}}> <View style={{display: 'none'}}> </View> </View>

works for me.

njacobs5074 commented 6 years ago

On our app, we use style overlays for different devices (phones vs tablets) and so was able to implement a workaround by using position: 'relative' for our phone style. Not 100% ideal but it works in our limited circumstance.

react-native-bot commented 6 years ago

Thanks for posting this! It looks like your issue may refer to an older version of React Native. Can you reproduce the issue on the latest release, v0.55?

Thank you for your contributions.

bisht2ankit commented 6 years ago

@forkbomb Thanks.. Worked for me.. But can you explain why its not working if we put position absolute and display none in a single view?

njacobs5074 commented 6 years ago

We see this issue on v0.55.4, btw. But the workaround I posted above addresses the issue for us on that release.

Yibay commented 6 years ago

I also want to submit this issue and find that someone has submitted it. 0.55.4

neilzhengzx commented 6 years ago

me too. 0.55.4

pdkn commented 6 years ago

me too. 0.55.4 any idea if it's fixed in 0.56?

z-zp commented 6 years ago
<View style={{
          position: 'absolute',
          bottom: 100,
          left: -30,
          backgroundColor: 'blue',
          borderColor: 'red',
          borderWidth: 9,
        }}>
       <View  style={{
          position: 'relative',
          display: 'none',
        }}>
          <Text> Hey Hey Hey Hey Hey </Text>
        </View>
</View>
verybluebot commented 6 years ago

same issue, can't solve it by upgrading to 0.56 because other chain of issues

ketn commented 6 years ago

This issue still exists in react-native@0.56. Is there a fix other than two views individually having position and display properties?

danielgindi commented 6 years ago

This exists in 0.57. So weird.

tatane616 commented 6 years ago

me too. 0.57

syq7970 commented 6 years ago

+1 0.57

basaamp commented 6 years ago

an idea for a single view with function change

if (visible) { //display nothing with position relative setState({display: none, position: relative})

} else { //display something with position absolute or relative setState({display: flex, position: absolute or relative} ) }

sercanov commented 5 years ago

Still exist on 0.57.7

yqz0203 commented 5 years ago

Still exist on 0.57.8,whoops!

ligaofeng0901 commented 5 years ago

Is there anyone who can fix it?

ferrannp commented 5 years ago

Can confirm this bug happens on 0.59.x.

yuweiguocn commented 5 years ago
<View style={{
          position: 'absolute',
          bottom: 100,
          left: -30,
          backgroundColor: 'blue',
          borderColor: 'red',
          borderWidth: 9,
          height:0,
          width:0,
        }}>
          <Text> Hey Hey Hey Hey Hey </Text>
        </View>
bohehe commented 5 years ago

Any good news for this issue ?

brandtnewlabs commented 5 years ago

Running into this issue too ... I mean: This is 1 1/2 years old. And I guess it's necessary to display toasts on both OS.

saeedhassankhan commented 5 years ago

when you want to change display to 'none' switch position from 'absolute' to 'relative'

ipankajgarg commented 4 years ago

Yeah display:none doesn't work with position:absolute! But only with android It works fine with IOS but there are several options that you can use :- opacity , visibility , z-index...

xdajay commented 4 years ago

Facing a similar issue with Android, Plus its a tooltip really can't get rid of position absolute. Opacity creates touches and visibility, Zindex isn't working either.

Any update on this issue?

Update: Wrapping around other View works!

fabOnReact commented 4 years ago

I gave it a quick look

maybe this is not connected to react native but to https://github.com/facebook/yoga

setPosition uses Yoga to set each position

https://github.com/facebook/react-native/blob/60b7a3085c0d83c126023b98e666ecda6f769454/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java#L946-L949

setDisplay uses Yoga to set display: none

https://github.com/facebook/react-native/blob/60b7a3085c0d83c126023b98e666ecda6f769454/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java#L857-L860

The two logic seems to conflict, so an Idea would be to create a reproducible example using android and yoga and open an issue at https://github.com/facebook/yoga/issues

I don't think that it is easy to troubleshoot this without building Yoga from source but I did not try extensively, because I would like to debug the Yoga code

https://github.com/facebook/yoga#building

I just judge this issues as very hard to solve for react-native contributor

rptoma commented 4 years ago

Still happening in RN 0.61.5

xaiamov commented 4 years ago

The same story in RN 0.62.2

younes200 commented 4 years ago

same on RN 0.63.0

thomasDelaporte commented 3 years ago

Same issue on React native expo sdk-40.0.1.

fabOnReact commented 3 years ago

https://github.com/facebook/react-native/issues/30338#issuecomment-786704700 Can you reproduce this without react-native using https://github.com/facebook/yoga as a dependency? Maybe it is an issue with facebook/yoga dependency and not react-native

We need to reproduce this without react-native, by building from source https://github.com/facebook/yoga and then debug the sourcecode, as I believe the relevant sourcecode for this problem is not included in react-native.

If we can reproduce the problem without react-native, you can open an issue in https://github.com/facebook/yoga, this problem will get fixed.. otherwise we may never find a solution

The functionality seems to be part of yoga, was developed with pr https://github.com/facebook/yoga/pull/369 to close https://github.com/facebook/yoga/issues/241 and https://github.com/facebook/yoga/pull/302

https://github.com/woehrl01/yoga/blob/29c60b81c361edb5861168e7085144f6bb80e5c2/yoga/Yoga.c#L1934-L1939

    if (child->style.display == YGDisplayNone) {
      YGZeroOutLayoutRecursivly(child);
      child->hasNewLayout = true;
      child->isDirty = false;
      continue;
    }

Thanks :peace_symbol: :smiley:

rnike commented 3 years ago

Still an issue on 0.64.0-rc.3

maki3000 commented 3 years ago

Another workaround which might help. We apply a black overlay with just one button inside (we make our own power save mode for OLED devices :) because our app can't go into background...). The button is visible all the time.

<View style={styles.container}>
      <StatusBar
        animated={true}
        showHideTransition={"fade"}
        barStyle={"dark-content"}
        hidden={savePower}
      />
      <View style={styles.powerSaveContainer}>
        <TouchableOpacity style={styles.powerSaveButton} onPress={setPowerSaveMode}>
          <Text style={styles.powerSaveButtonText}>{savePowerText}</Text>
        </TouchableOpacity>
      </View>
      <View style={[
        savePower ? {
          backgroundColor: "#000000",
          zIndex: 100,
        } : {
          backgroundColor: Colors.defaultBackground,
          zIndex: -10,
        },
        styles.powerSaveOverlayContainer
      ]}>
      </View>
      <View style={styles.innerContainer}>
          {/* other content */}
     </View>
</View>

And the styles:

const styles = StyleSheet.create({
  container: {
    alignItems: 'center',
    backgroundColor: Colors.defaultBackground,
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 16,
    paddingTop: 32,
  },
  powerSaveOverlayContainer: {
    bottom: 0,
    left: 0,
    position: "absolute",
    right: 0,
    top: 0,
  },
  innerContainer: {
    alignItems: 'center',
    flex: 1,
    justifyContent: 'center',
  },
  powerSaveContainer: {
    flexDirection: "row",
    justifyContent: "space-between",
    paddingTop: 18,
    zIndex: 1000,
  },
  powerSaveButton: {
    backgroundColor: "#8C8989",
    borderColor: "#999999",
    borderRadius: 120,
    borderWidth: 1,
    margin: 8,
  },
  powerSaveButtonText: {
    color: "#ffffff",
    padding: 12,
  },
});

We toggle savePower in setPowerSaveMode method and work with same backgroundColor as the container when not visible and black backgroundColor when visible and apply different zIndex.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] commented 1 year ago

This issue was closed because it has been stalled for 7 days with no activity.