I'm using Flatlist in HomeScreen and it shows me multiple posts. So now what I want is whenever I Signout from the app or close the app and then open the app, I should be able to see the first item from Flatlist.
I've tried using scrollToIndex inside my render function but it gave me an error - undefined is not an object (evaluating '_this2.refs.flatListRef.scrollToIndex')
<FlatList
data={this.state.data}
ref={(ref) => { this.flatListRef = ref; }}
renderItem={ ({item,index}) => this._renderItem(item,index) }
extraData={[ this.state.data, this.state.checked ]}
/>
And this is what I tried using in componentDidMount and inside render function this.refs.flatListRef.scrollToIndex({animated: true,index:0}); but didn't work.
ComponentDidMount callbacks won't run after the user leaves the app and resumes it later. You have to use AppState instead:
AppState can tell you if the app is in the foreground or background, and notify you when the state changes. [Source]
Adapt the given example to your needs and scroll with this.flatListRef.scrollToIndex({animated: true,index:0})}
import {
ScrollView,
} from 'react-native';
import {useScrollToTop} from '#react-navigation/native';
const ref = React.useRef(null);
useScrollToTop(ref);
const goToTopClickAction = () => {
ref.current?.scrollTo({
y: 0,
animated: true,
});
};
add ref={ref} in ScrollView tag
< ScrollView ref={ref}> < /ScrollView >
Related
TouchableOpacity onPress is not working inside Flatlist but when I replaced onPress with onPressIn/onPressOut it is working fine, but in that case the reaction is too fast and having issue while scrolling. I don''t know what it is happening and haven't found any related issue. Below is my code:
renderItem = ({ item, index }: { item: any, index: number }) => {
const { type } = this.props;
const valueType = {
phone: item,
stage: item.title,
location: item.name
}
return (
<TouchableOpacity
onPressIn={() => this.onSelect(item, index)}
style={styles.modalListContainer}
>
<Icon name={icon[type]} height={20} width={20}/>
<Spacer width={10} />
<View style={styles.modelTextContainer}>
<Text style={styles.modelText}>{valueType[type]}</Text>
</View>
</TouchableOpacity>
)
}
<FlatList
data={item}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
ItemSeparatorComponent={() => <><Spacer height={10} /><View style={styles.modelTextDevider} /><Spacer height={10} /></>}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.container}
/>
It is rendered inside a Modal using react-native-modals library. Any help would be appreciated.
Thank you.
react-native-modals, have a parent touchable component (PanResponder) which wraps your children's components. On some android devices, when you have a touchable component like a button, the touch event does not propagate down to child component instead capture by react-native-modals parent component.
The ideal solution should be absolute positioning your button but will break your UI and the modal will be useless.
There's an existing issue with this library repository.
https://github.com/jacklam718/react-native-modals/pull/210
but the solution provided is not 100% accurate for Android devices.
If you're using React Navigation, you already installed react-native-gesture-handler.
import TouchableOpacity from react-native-gesture-handler in place of `react-native. It should solve the issue for most devices.
I'm having an intermittent problem with the TouchableOpacity component in react-native.
I basically click on the element, it performs the opacity animation normally, but my console.log runs randomly. In iOS works correctly.
My code:
<TouchableOpacity style={{backgroundColor:'red'}} onPress={async () => {
console.log('Button '+item.tag+' pressed.');
}}>
NOTE: I've tried calling this function without async.
I found the solution!
PanResponder was detecting micro movements on simple touch. In the onMoveShouldSetPanResponder parameter I defined the following function:
panResponder = PanResponder.create({
onMoveShouldSetPanResponder: (e, g) => {
return Math.abs(g.dx) > 2 || Math.abs(g.dy) > 2;
},
...
});
I am experiencing a very weird behaviour in my android emulator when using react-navigation v5 in my react native application, which makes me think is a bug. I found out that there is an open issue on the official react-native-navigation page. See here.
In every secondary screen (see UserProfileScreen below), in many react native-elements like TouchableOpacity Button or TextInput the onPress event doesn't work. It only works in the main screen of the navigator. (See HomeScreen below)
Here is an example of how I create my stack navigator:
import {createStackNavigator} from '#react-navigation/stack';
// some imports here
const HomeStackNavigator = createStackNavigator();
export const HomeNavigator = () => {
return (
<HomeStackNavigator.Navigator>
<HomeStackNavigator.Screen name="HomeScreen" component={HomeScreen}/>
<HomeStackNavigator.Screen name="UserProfileScreen" component={UserProfileScreen}/>
<HomeStackNavigator.Screen name="UserSettingsScreen" component={UserSettingsScreen}/>
</HomeStackNavigator.Navigator>
)
};
As a PoC I have the same code in the main and secondary screen:
<TouchableOpacity
onPress={() => Alert.alert("You pressed me!")} >
<Text> touch me</Text>
</TouchableOpacity>
and I see the alert only in the main screen (HomeScreen).
If I make UserProfileScreen as the fist screen in my stack navigator above then it works (the onPress event) fine on this screen but not in the HomeScreen. So it seems that the onPress event is triggered only in the main screen!. On IOS it works fine in all screens. Any idea ? Let me know if you need some more code snippets.
I'm trying to set the refresh indicator of flat list in react native but don't know how to do it. List View has this prop :
refreshControl={<RefreshControl
colors={["#9Bd35A", "#689F38"]}
refreshing={this.props.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}
But Flat List has only these :
refreshing={this.props.loading}
onRefresh={this._onRefresh.bind(this)}
I found the solution! It might be the dummy but FlatList also has a prop called refreshControl like ListView but I just didn't test it! Just like this:
<FlatList
refreshControl={<RefreshControl
colors={["#9Bd35A", "#689F38"]}
refreshing={this.props.refreshing}
onRefresh={this._onRefresh.bind(this)} />}
/>
refreshControl={
<RefreshControl
isRefreshing={isRefreshing}
onRefresh={loadProducts}
colors={[Colors.GreenLight]} // for android
tintColor={Colors.GreenLight} // for ios
/>
}
this covers both ios and android
In official doc for RefreshControl component it is stated as - This component is used inside a ScrollView or ListView to add pull to refresh functionality. When the ScrollView is at scrollY: 0, swiping down triggers an onRefresh event
So for FlatList don't use it directly because they provides the two special props named as refreshing and onRefresh - on which the standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop.
USAGE -
Step 1:
const wait = (timeout) => { // Defined the timeout function for testing purpose
return new Promise(resolve => setTimeout(resolve, timeout));
}
const [isRefreshing, setIsRefreshing] = useState(false);
const onRefresh = useCallback(() => {
setIsRefreshing(true);
wait(2000).then(() => setIsRefreshing(false));
}, []);
Step 2:
Now use component as
<FlatList
style={styles.flatListStyle}
data={inProgressProjects.current}
keyExtractor={item => item._id}
renderItem={renderItem}
showsVerticalScrollIndicator={false}
refreshing={isRefreshing} // Added pull to refesh state
onRefresh={onRefresh} // Added pull to refresh control
/>
For more information refer here -
https://reactnative.dev/docs/refreshcontrol
https://reactnative.dev/docs/flatlist#onrefresh
Hope this will help you or somebody else.
Thanks!
You can pass in the renderScrollComponent to your FlatList component with the same RefreshControl component you have showed above. I have created a expo snack for this: https://snack.expo.io/rJ7a6BCvW
The FlatList is using VirtualizedList within itself, and for VirtualizedList component, it takes a renderScrollComponent: https://facebook.github.io/react-native/docs/virtualizedlist.html#renderscrollcomponent
I was passing bounces={false} to my Flatlist which was causing problem. This will not allow you to refresh. Remove it if you want to use the above one solution mentioned. Thanks
I have at the moment a component SplashScreen which I'm rendering first till my state is set. I would like somehow to find a way how to still show this component while my webview is loaded. I added the onLoadEnd to my webview and looks like I get my message back when its finished loading, the problem is that if I load first the splashscreen and wait for the state to be changed onLoadEnd actually will never be changed because the webview is not yet rendered. Is there a good method how to do this?
My solution was actually quite simple, the WebView component can have the param renderLoading which for me was not working, I figured out it was because also startInLoadingState needed to be defined.
So my WebView looks somehow like this:
<WebView
ref={MY_REF}
source={source}
renderLoading={this.renderLoading}
startInLoadingState
/>
This would be my approach:
constructor(props){
super(props);
this.state = { webviewLoaded: false };
}
_onLoadEnd() {
this.setState({ webviewLoaded: true });
}
render() {
return(
<View>
{(this.state.webviewLoaded) ? null : <SplashScreen />}
<WebView onLoadEnd={this._onLoadEnd.bind(this)} />
</View>
)
}
This way, the webview is rendered but it is placed behind the SplashScreen. So the webview starts loading while the SplashScreen is being displayed.
I had a similar problem and I managed to solve it temporarily with this:
loadEnd () {
this.setState({ webViewLoaded: true }):
}
render () {
const { webViewLoaded } = this.state;
return (<View>
{!webViewLoaded && <LoadingComponent /> } -- or spinner, whatever
<WebView
style={(webViewLoaded) ? styles.webView : styles.loading}
onLoadEnd={() => this.loadEnd.bind(this)} />
</View);
}
const styles = StyleSheet.create({
webView: { -- your styles ---},
loading: {
width: 0,
heigt: 0
}
});
not sure if exactly this helps you but you can try similar approach. I will probably change this to something more convenient. Not sure if there are possibilities to animate these changes because Im still pretty newbie in React Native.
edit: added hiding the spinner/loading element