Scrolling to the bottom of a ScrollView on initial load - react-native

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

Related

Flatlist of buttons does not render on first navigation

I have a Stack.Navigator, when I navigate to a page that contains my FlatList which renders 4x6 items at once, all of the other components will render and the flatlist will be invisible/not rendered. The app then locks up, and then after that the flatlist renders all the items and the layout is bumped around which is not desirable. Is this expected behaviour and what can I do about it? I'd prefer the whole app freeze/stutter until all of the first page is ready to show at once, rather than rendering everything but the Flatlist and then bumping the UI around.
The FlatList component is very uncontroversial as far as I can see.
<View>
<FlatList
numColumns={4}
columnWrapperStyle={styles.colWrap}
keyExtractor={(theitem) => theitem.id}
renderItem={renderIndividualSound(onSoundButtonPress)}
data={soundPage}
key="soundspage"
/>
</View>
Upon further inspection, I was using a useState() hook that init'd with a blank array, and then using a useEffect(()=>{}, []) hook to update the state once at initialisation, meaning a blank list was passed through for the very first render.

Controlling how far to scroll in flat list. React native

Good day guys , is there anyway I can control how far the flatlist can scroll ? I'm trying to make an image viewer. When there is multiple image , the user can scroll to the 2nd image without reaching the 3rd image. Thank you. Expected outcome :
Either you can use a library like react native snap carousel
or use the function of scrollToIndex inside any function ,so that you can control which index the user goes ==
scrollToNext(){
this.flatListRef.scrollToIndex({animated: true, index: newIndex});
}
<Flatlist
ref={ref => {
this.flatListRef = ref;
}}
/>
hope it helps. feel free for updates

React-Native: How to know when the rendering got finished

I have FlatList in render() function with a reference,
<FlatList
ref={(ref) => { this.flatListRef = ref }}
data={this.state.data}
renderItem={({ item, index }) => this.renderOuterCard(item, index)}
/>
I need to use this.flatListRef to call FlatList's methods, which is possible only when FlatList is rendered. Otherwise following error occurs,
Cannot read the property 'ScrollToIndex' of undefined
(I tried to call FlatList's ScrollTOIndex method)
Infact I called ScrollTOIndex in componentDidMount() method , But still this error occurs. Hence, This is clear that componentDidMount() is called before render() finishes completely.
Can anybody let me know when rendering finishes exactly?
This is clear that componentDidMount() is called before render() finishes completely.
According to this schema the first render phase occur before componentDidMount.
http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
 Live example:
https://snack.expo.io/#flexbox/flatlist-with-state-example
I am having the same issue. I do have a Component that uses FlatList and I would like to know when, within the first render, the list has rendered the visible items (ready state).
I have discovered that on the main component the componentDidMount was triggered because the FlatList component have mounted as well. And because FlatList Component asyncronously renders each item they only show up after on componentDidUpdate.
I have struggled for a while and even with the componentDidUpdate approach I could only get the moment where FlatList got new data (not rendered the items).
So I found out that I could intercept the renderItem method to create some logic to better estimate what and when is being rendered. The other option was to have a setTimeout (very hacky) to trigger the work based on a average time (very poor solution).
If someone have a proper approach to be able to know when the FlatList finishes rendering the inView items please share.
Thanks.

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.

TouchableHighlight and TouchableOpacity get highlighted on render()

I experience a behaviour where TouchableHighlight and TouchableOpacity reacts visually upon render (onPress is not being called).
One thing is that it looks just a little strange, when I enter the page and my button make a small "blink". This is strange but tolerable. The more frustrating part is that if I alter state for the parent component and thus invoke a re-render(), the button will "blink" again, making all buttons blink whenever I alter state.
Pushing the buttons alters page state, and thus pushing a button makes both buttons "blink".
I use react-redux, but this should not affect this behaviour.
The code below is just for illustration.
render()
{
return(
<View>
<ToucableHightlight> //Click here changes state
<Content/>
</ToucableHightlight>
<ToucableHightlight> //Click here changes state
<Content/>
</ToucableHightlight>
<View>
);
}
Add activeOpacity in TouchableOpacity and it will force to not blink.
<TouchableOpacity style={styles.opecity} activeOpacity={1}>
I solved the problem. Earlier during my render function i defined the "Content"-components, resulting in new (but alike) components being defined during each update. Placing the definitions of "Content" outside of the render function fixed it, so that the components no longer flashes when the page is re-rendered.
This explains why my component was rendered as a new component upon each render in the parent component, but it does not explain why a TouchableHighlight blinks during its initial render.
Buttons blinking during initial render is acceptable to me - buttons blinking upon any state-change is not.
So I am sufficiently happy now.
Not sure if it's because I'm running a later version, but I found this blinking behavior happens only on the first click.
My solution was putting the code that triggers rerendering in a setTimeout
<TouchableOpacity
onPress={function() {
setTimeout(function() {
_this.setState({myState: 'someValue'})
});
}}
>