Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using display none instead of condition state rendering

I m trying to use conditional rendering (in this specific case) that would allow me to make something like :

<Image
    source={{ uri: "https://images4.alphacoders.com/221/221716.jpg" }}
    style={this.state.isLoaded ? styles.loaded : { display: "none" }}
    onLoadEnd={() => {
    console.log("test"), this.setState({ isLoaded: true });
    }}
/>

The main problem is that React Native doesn't seem to be able to use its internal lifecycle functions when the display: none style is used, and thus doesn't call onLoadEnd. It doesn't log anything.

I don't have any idea how to encounter this problem while using display style props

like image 243
mfrachet Avatar asked Nov 19 '17 14:11

mfrachet


People also ask

How do I stop state changes from rendering?

Avoid The State Update The most straightforward approach to preventing state update re-renders is by avoiding the state update entirely. This means making sure that the setState function is not called unless strictly necessary.

Can we set state in the render method?

The render() function should be pure, meaning that it does not modify a component's state. It returns the same result each time it's invoked, and it does not directly interact with the browser. In this case, avoid using setState() here.

Does changing state cause re-render?

There are four reasons why a component would re-render itself: state changes, parent (or children) re-renders, context changes, and hooks changes. There is also a big myth: that re-renders happen when the component's props change.


2 Answers

TL;TR

{ transform: [{ scale: 0 }] } is a good solution

IMHO,

your question about lifecyle / rendering seems legit.
Since i can't give any answer actually...
I got some weird bug recently trying to use { display: 'none' } (when restoring display to 'flex' some children component still didn't render), or { width: 0, height: 0 } (when back to 'flex' the layout was not restored).
Needless to say that avoiding rendering via some was usual tricks ( return enabled && <MyComponent {...}/>) was not the solution (mounting & unmounting components requires heavy computations that are breaking animations framerate).

As i was looking to hide components during animations without break the framerate, i found that { transform: [{ scale: 0 }] } was the best solution:

  • layout is not altered (alignSelf: 'center' still works).
  • the hidden component won't catch any touch events and allow underlying components to react to touches.

my implementation is something like

view.setNativeProps({ transform: [{ scale: 0 }]
like image 85
Joseph Merdrignac Avatar answered Sep 26 '22 12:09

Joseph Merdrignac


Next time, it would be super cool if you setup a snack to demo your issue.

This pattern will work for you...

<Image
  source={{ uri: "https://images4.alphacoders.com/221/221716.jpg" }}
  style={[{width: 0, height: 0,},
  this.state.isLoaded && {width: 400, height: 400,}]}
  resizeMode="contain"
  onLoadEnd={() => {
    this.setState({ isLoaded: true });
  }}
/>

I've created a demo on snack for you

update with display: none

<Image
  source={{ uri: "https://images4.alphacoders.com/221/221716.jpg" }}
  style={[{width: 400, height: 400,},
  !this.state.isLoaded && {display: 'none'}]}
  resizeMode="contain"
  onLoadEnd={() => {
    this.setState({ isLoaded: true });
  }}
/>
like image 36
Chris Geirman Avatar answered Sep 22 '22 12:09

Chris Geirman