React Native Dimensions not working on rotation - react-native

I am running the code posted (for Class Component) at:
https://reactnative.dev/docs/dimensions
Yet, at the Android Studio simulator, If I "rotate" the device the dimension's values do not change i.e. I was expecting that the height and width could change with the rotation but this is not happening. Any ideas why?
According to the info posted at the previous link it says:
Although dimensions are available immediately, they may change (e.g due to device rotation, foldable devices etc) so any rendering logic or styles that depend on these constants should try to call this function on every render, rather than caching the value (for example, using inline styles rather than setting a value in a StyleSheet).
I also tried using using useWindowDimensions but this is limited to functional react components.
So far, I can not find a reliable way to detect if an Android device rotated using React-Native and class components :-(
Note: This problem also happens with React Function Component

Try: https://reactnative.dev/docs/usewindowdimensions
It works for me
import { useWindowDimensions } from 'react-native';
const { height, width } = useWindowDimensions();

I had the same problem. Upgrading react-native to version 0.64.2 fixed it.

My problem on 0.61.5 was not that the values were not correct, but that the view was not re-rendered at all after the rotation, so I added this to the constructor() and it worked:
Dimensions.addEventListener('change', () => {
this.setState({});
});

Related

react-native-webview avoid keyboard (iOS)

The react-native-webview has in my experience proved difficult to behave as I want around the keyboard on iOS. It doesn't automatically change it's height when the keyboard is shown and its contents gets concealed by the keyboard.
It also behaves strangely wrapped with the KeyboardAvoidingView. In my case it seems to adjust the content of the WebView too much, approximately twice the height of the keyboard. This same behavior appeared when I manually listened for the keyboard open/close events and adjusted the height of the WebView accordingly:
componentDidMount(){
Keyboard.addListener("keyboardWillShow", this.keyboardDidShow.bind(this));
Keyboard.addListener("keyboardWillHide", this.keyboardDidHide.bind(this));
}
componentWillUnmount(){
Keyboard.removeListener("keyboardWillShow", this.keyboardDidShow.bind(this));
Keyboard.removeListener("keyboardWillHide", this.keyboardDidHide.bind(this));
}
keyboardDidShow(event){
this.setState({
keyboardHeight: event.endCoordinates.height
});
}
keyboardDidHide(event){
this.setState({
keyboardHeight: 0
});
}
render(){
return (
<WebView
style={{flex: 1, maxHeight: Dimensions.get("window").height - this.state.keyboardHeight}}
/>
);
}
I've found a solution, not optimal, but a solution non the less. My answer is posted below.
As I couldn't find any discussions on this particular behavior and no solutions that worked for me, I worked my way through the props of the react-native-webview docs. What finally worked for me in version 0.59.9 of React Native and version 5.11.0 of React Native WebView was as described above, manually setting the height of the WebView in the keyboard event listeners and setting the WebView prop useWebKit={false}.
Unfortunately this means that on the native side of the WebView, it's now using UIWebView which is deprecated and will in a future release be deleted.
Either way, this is what I'm rolling with and simply wanted to share my findings in case anyone finds themselves with the same issue.

React Native Custom Icons w/ Vector Icons

I'm new to React Native and I'm trying to have icons that are able to have their color changed based on json data received. I've been able to use React Native Vector Icons. However, I have my own icons that I would like to use. On the linked repo page there is something that talks about generating your own icons, but I'm not familiar enough to know how it is supposed to work. My icons are .png files and I'd like to make them so I can give them a color attribute on the fly in my app. I wanted to see what the process was to be able to do that if it was even possible. Can I use the process described in the repo?
Thanks in advance!
So, to create your own icon component, this could be a simple representation:
import React from 'react'
import { View, Image } from 'react-native'
export default class Example extends React.Component{
renderIcon = (iconName, color) => {
iconName = this.props.iconName
color = this.props.color
return<Image source={require(`/example/icons/${exampleIcon}${color}.png`)}/>
}
render(){
return(
<View>
{this._renderIcon}
</View>
)
}
}
For example, your .png Icon is called IconHomeFocused, and it's an icon of the home icon when it's focused...then you would put, in your component that you want your Icon to be in: <Example iconName = 'IconHome' color = 'Focused'/>. Of course, this requires you to name your icons carefully. I didn't want to write a million if statements so this seemed like the easiest sort of integration for me. I'm sure there are much better interpretations out there though. Good luck.

React native detect screen rotation

I'm using onLayout to detect screen orientation and it's working fine inside my root view, but when I implemented inside the drawer it didn't work, any reason why this happens ?
code :
import Drawer from 'react-native-drawer'
...
onLayout(e) {
console.log('onLayout');
}
<Drawer onLayout={this.onLayout}
It didn't log any thing when orientation changed!
This is because the Drawer component doesn't take onLayout as a prop. You can see in the source code that the rendered View does use onLayout, but it's not pulling from something like this.props.onLayout.
I'm not exactly sure what you're looking to do, but maybe this issue will help you. As it shows, you can pass a function into openDrawerOffset instead of an integer or a ratio in order to be a little more dynamic with how you set your offset:
openDrawerOffset={(viewport) => {
if (viewport.width < 400) {
return viewport.width * 0.1;
}
return viewport.width - 400;
}}
You might also benefit from the Event handlers that react-native-drawer has to offer.

Why is Flow/Nuclide showing me a warning "not covered by Flow" in my React-Native component?

I'm starting to use flow and have a simple component :
// #flow
import React, { Component } from 'react';
import {
Text,
ScrollView
} from 'react-native';
const Conversations = (props: { messages: string }) => (
<ScrollView>
<Text>{props.messages}</Text>
</ScrollView>
);
export default Conversations;
In Nuclide, I see this warning "Warning, type coverage, not covered by Flow". It's pointing at line 9, where I use <ScrollView>.
Why is that / What does it mean / How can I fix it ?
You have turned on the type coverage feature (see screenshot). You can click the percentage in the status bar to toggle it on and off. It lets you know which expressions Flow has types for, and which ones are untyped (meaning you can do anything with them and Flow will not warn you).
The React Native team simply hasn't added Flowtypes to the core components yet.
From the official react native roadmap :
Flowtyping the core components. Owners: yungsters, alex_frantic. ETA: January
Making the most common components come with Flow types, for a
better typechecking experience. This should also make it easier to
reduce breaking changes. Flow already comes with React Native, so this
is a logical step to further improve the experience.
https://github.com/facebook/react-native/wiki/Roadmap/ebdbdc699bc083b98ac7b067465218fd70d30b66

Using CSS filters in react-native

It seems that react-native doesn't implement CSS' filter property.
Is there a way to replicate those? Specifically I am looking for a way to change the following to an image, without creating a special image just for that:
Brightness
Hue
Saturation
Blur
Blur for images is already supported by RN via blurRadius prop. The remaining filters you can find in my react-native-color-matrix-image-filters library:
import { Image } from 'react-native';
import { Saturate } from 'react-native-color-matrix-image-filters';
const SaturatedImage = ({ saturate, ...imageProps }) => (
<Saturate value={saturate}>
<Image {...imageProps} />
</Saturate>
);
Update RN 0.62.2:
I was using above mentioned Library react-native-color-matrix-image-filters, but I was looking for web support too. As of right now React Native for web supports the css filter property: https://github.com/ndbroadbent/react-native-web/blob/91e4528eac16e10fd3d42644fc4c0c8047bee1bd/docs/components/View.md
For iOS and Android this style property does not work.