Search code examples
cssreactjsscreen-orientationreact-native

React Native: Different styles applied on orientation change


I'm developing a React Native application to be deployed as a native application on iOS and Android (and Windows, if possible).

The problem is that we want the layout to be different depending on screen dimensions and its orientation.

I've made some functions that return the styles object and are called on every component render's function, so I am able to apply different styles at application startup, but if the orientation (or screen's size) changes once the app has been initialized, they aren't recalculated nor reapplied.

I've added listeners to the top rendered so it updates its state on orientation change (and it forces a render for the rest of the application), but the subcomponents are not rerendering (because, in fact, they have not been changed).

So, my question is: how can I make to have styles that may be completely different based on screen size and orientation, just as with CSS Media Queries (which are rendered on the fly)?

I've already tried react-native-responsive module without luck.

Thank you!


Solution

  • Finally, I've been able to do so. Don't know the performance issues it can carry, but they should not be a problem since it's only called on resizing or orientation change.

    I've made a global controller where I have a function which receives the component (the container, the view) and adds an event listener to it:

    const getScreenInfo = () => {
        const dim = Dimensions.get('window');
        return dim;
    }    
    
    const bindScreenDimensionsUpdate = (component) => {
        Dimensions.addEventListener('change', () => {
            try{
                component.setState({
                    orientation: isPortrait() ? 'portrait' : 'landscape',
                    screenWidth: getScreenInfo().width,
                    screenHeight: getScreenInfo().height
                });
            }catch(e){
                // Fail silently
            }
        });
    }
    

    With this, I force to rerender the component when there's a change on orientation, or on window resizing.

    Then, on every component constructor:

    import ScreenMetrics from './globalFunctionContainer';
    
    export default class UserList extends Component {
      constructor(props){
        super(props);
    
        this.state = {};
    
        ScreenMetrics.bindScreenDimensionsUpdate(this);
      }
    }
    

    This way, it gets rerendered everytime there's a window resize or an orientation change.

    You should note, however, that this must be applied to every component which we want to listen to orientation changes, since if the parent container is updated but the state (or props) of the children do not update, they won't be rerendered, so it can be a performance kill if we have a big children tree listening to it.

    Hope it helps someone!