React native detect screen rotation - react-native

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.

Related

Is there a way to animate the increased size of a View when new children are added?

I’m currently using LayoutAnimation to animate a view when children are added. However, since LayoutAnimation causes everything to be animated, globally, and I can’t easily use built-in Animated library to fit my use-case, I’m wondering if react-native-reanimated is able to help.
Here's a snack of my current solution:
https://snack.expo.io/#insats/height-adapation
This is what the result of that looks like:
Is there a way to achieve the same thing without using LayoutAnimation? I've looked through all exampled in react-native-reanimated, and I've read through the docs but I'm still not sure if this is possible to do or how I should get started. I've thought about using Animated to move the item-wrapper out of the viewable area and "scroll" it upwards (using transform translateY) when items are added, but that would require fixed height, which I don't have.
I have 2 approaches that I can suggest out of my mind:
You can configure your LayoutAnimation only when your desired state changed. If you use hooks it would be too easy:
const [state,setState] = useState([]);
useEffect(()=>{
/*rest code*/
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
},[state])
Or if you use class component you can catch your desired state change in componentDidUpdate:
componentDidUpdate(prevProps,prevState){
if(prevState.items!==state.items){
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
}
}
You can use onLayout function of view:
addItem = () => {
this.setState({
items: [...this.state.items, {title:'An item',isNew:true}]
})
};
renderItems = () => {
return this.state.items.map((item, index) => {
let opacity = new Animated.Value(0);
return (
<Animated.View onLayout={({nativeEvent})=>{
if(this.state.item.isNew){
// here you got the height from nativeEvent.layout.height
// Then you have to store the height animate height and opacity to its precise value
// PS I used opacity:0 to calculate the height
}
}} key={index} style={[styles.item,{opacity}>
<Text>{item.title}</Text>
</View>
)
});
};
When it comes to react-native-reanimated I regard it as more faster version of react-native's Animated library. So either way you will have to calculate the height!

Scrolling to the bottom of a ScrollView on initial load

I have a large long image with a few inputs at the bottom in my react native view. When the view loads I want it to be "scrolled" to the bottom of the page -- all the examples I can find online are triggered because of some event that the user does.
I want to call scrollToEnd() but I'm not sure where in the lifecycle the ref will actually be set -- anyone have ideas?
Use scrollToEnd this way. It will take to the bottom of ScrollView
<ScrollView
ref={ref => this.scrollView = ref}
onContentSizeChange={(contentWidth, contentHeight)=>{
this.scrollView.scrollToEnd({animated: true});
}}>
I am not clear with your question but
With react-native Image component we have onLoad prop. I think this is what you are looking for.
try something like:
<Image source={{uri...}} onLoad={(e)=>this.handleImageLoaded(e)}/>
then inside handleImageLoaded method you can use scrollToEnd() with some ref as per your code.
also there are other useful props like onLoadStart/End check here
https://facebook.github.io/react-native/docs/image
Or if you are just waiting for the view to render then to scroll
for that I think componentDidAppear() lifecycle method, if using react-native -navigation by wix
or with react-navigation
willFocus, willBlur, didFocus and didBlur events for the component render cycle.. explained here
https://reactnavigation.org/docs/en/navigation-prop.html#addlistener-subscribe-to-updates-to-navigation-lifecycle

How to add enum image source to React-native-circle-button?

I am trying to add a custom image source to the attribute iconButtonCenter in the React Native library named react-native-circle-button.
https://github.com/dwicao/react-native-circle-button
According to the documentation, iconButtonCenter is of type enum, so I imported the icon and then passed it in directly where I create my CircleButton object. It does not yell as if it is a number or string, yet I still am not 100% sure it is technically of type enum. I know for a fact it is finding the image in the right path. I also know that it is doing something, because the default image is no longer observable on the app, it just no longer has an icon. I am not getting any compilation errors or warning, yet I still do not see the icon appear over the button as it should. How do I fix this?
Here is the render within my component that allows circle button's to be draggable. I also went ahead and put my import at the top so you can see how this was stored.
import letterA from '../assets/letters/alpha-a.svg';
render() {
let { pan } = this.state;
let [translateX, translateY] = [pan.x, pan.y];
let moveableStyle = {transform: [{translateX}, {translateY}]};
const panStyle = {
transform: this.state.pan.getTranslateTransform()
}
return (
<Animated.View
{...this._panResponder.panHandlers}
style={[moveableStyle, panStyle]}>
<CircleButton iconButtonCenter={letterA} /> <--- Here is the image source reference.
</Animated.View>
);
}
The CircleButton component should successfully have the image fed to it and remain centered over the button even when dragged along the string.
Problem was the picture format was an .svg, converting the icons to .png worked like a charm!

Rendering Components runtime during the navigation in react-native

I want to display a component(say, a View or Text component) in my current screen only if I return back to this screen from some other screen.
For e.g, say I am at the Home.js where I am displaying the view components. The count of this view components depends upon the number of times one goes(or visits) the Break.js screen. Like If i have visited the Break.js screen thrice, then there should be 3 View components available at the Home.js screen.
I am a beginner in React-Native, so don't have any idea how to implement this....I have gone through the similar query like
Dynamically rendering components - React Native and
React Native View Render
but couldn't understand anything. Pls help as I have nothing to show what I have tried so far.....
Below is one way of updating your component, where you update the viewCount before navigating to the other screen. This works only if the previous screen exists in the memory after navigation like in the cases of stack navigators. This is a basic idea which u can modify for your use case.
class HomeScreen extends Component {
onNavigate() {
this.updateViewCount();
// ... navigate to BreakScreen
}
updateViewCount() {
this.setState({numOfViews: this.state.numOfViews + 1});
}
render() {
// Create an array and push your elements based on count
// this.state.numOfViews manages the count
let views = [];
for(let i = 0; i <= this.state.numOfViews; i++) {
views.push(<SomeComponent />);
}
// Render your custom views
return(
<View>
{views}
<Button onPress={() => this.onNavigate()} />
</View>
);
}
}

react native route flux re-render component on stack pop

How do you re-run React Component Lifecycle methods to determine if a re-render is necessary when transitioning back to previous screens from stack using React Native Router Flux?
Scenario: Scene A -> B -> A
Lets say, A is the initial scene and we navigate from A to B with a push i.e Actions.SceneB. From B to A with a Pop. When the stack is popped to show Scene-A, none of the React Component methods are called for Scene-A. How do I determine if a re-render is necessary? I searched the Issues listed on the github repo and many seems to have this problem without a solution. How is this problem addressed?
I have the ugly work around of calling Actions.refresh() with a setTimeout.
Work Around that works!
This workaround seems to be hacky. There must be a better way to hook into component lifecycle to determine if a re-render is required. Perhaps a callback into the Component?
<TouchableHighlight underlayColor='#efefef' onPress={() => { Actions.pop(); setTimeout(()=> Actions.refresh(), 500)}} style={styles.cancel}>
Options that do not work
Actions.pop({type: 'reset'})
OR
Actions.refresh({"key" : "sceneA"})
Work Around that works! This workaround seems to be hacky. There must be a better way to hook into component lifecycle to determine if a re-render is required.
<TouchableHighlight underlayColor='#efefef' onPress={() => { Actions.pop(); setTimeout(()=> Actions.refresh(), 500)}} style={styles.cancel}>
This will call shouldComponentUpdate() method which gives an option to determine, if a re-render is required.
I was facing the same issue below code gave me required result.
let count = 0;
moveToMainScreen = () => {
count += 1;
Actions.pop({ refresh: { test: count } });
};
<Button onPress={this.moveToMainScreen}> Click </Button>