ScrollToIndex does not scroll the FlatList as expected - react-native

I have a FlatList setup like so
<FlatList
style={styles.listContainer}
data={this._formatList()}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
ItemSeparatorComponent={this.renderSeparator}
nestedScrollEnabled
showsVerticalScrollIndicator={false}
extraData={this.state}
ref={this._setRef}
/>
I also have these following two relevant functions in my component
_setRef = (ref) => {
this._listref = ref;
}
_scrollToTop = () => {
this._listref.scrollToIndex({ index: 0, animated: true });
}
I have checked that the this._listref is setup correctly when FlatList is rendered.
The function _scrollToTop is called from a button click (and it is indeed called).
For some reason the list does not scroll to top as expected.
I have tried various options playing with viewOffset / viewPosition.
It seems no scrolling action is taking place.
This is an expo project with "sdkVersion": "33.0.0"
and React and RN as follows from package.json
"react": "16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
Thanks.

From the docs: https://facebook.github.io/react-native/docs/flatlist#scrolltoindex
Note: Cannot scroll to locations outside the render window without
specifying the getItemLayout prop.
So you'll need to implement getItemLayout for scrolling to the top to work properly with scrollToIndex since most certainly it will be outside of the current render window.
You could alternatively use scrollToOffset: https://facebook.github.io/react-native/docs/flatlist#scrolltooffset with a param of {offset: 0} instead.

Have you tried using offset?
this.listRef.getNode().scrollToOffset({ offset: 0, animated: true });
OR
this.listRef.scrollToOffset({ animated: true, offset: 0 });
Trying using this and I hope this will work assuming that you've correctly set up the reference of the scrollview and passing that correctly in the function.

Related

React Native Testing Library: scroll FlatList to bottom

I have a react-native FlatList component with onEndReached event used to load more items.
I am testing the component with react-native-testing-library. The test is as follows:
Component mounted.
Requests 10 items to mockedBackend.
Expect FlatList to render those 10 items.
fireEvent onEndReached to ask for next page with some more items.
Expect FlatList to render new items.
Test was failing because FlatList was not rendering new items even thought FlatList's data property was being updated (I used act and waitFor as needed).
I managed to make the test pass when I fired onScroll event to bottom after some tries with hardcoded values.
Is there a way to make a helper to scroll to bottom taking into account proper FlatList size?
Helper to improve:
export const scrollListToBottom = (list: ReactTestInstance) => {
// FIXME: improve to get real list size
// After some tries these hardcoded values allowed to pass the test
act(() => {
fireEvent.scroll(list, {
nativeEvent: {
contentSize: {height: 500, width: 100},
contentOffset: {y: 400, x: 0},
layoutMeasurement: {height: 100, width: 100},
}
})
})
// FIXME: if onScroll works perfectly is this even needed?
act(() => {
fireEvent(list, 'onEndReached')
})
}
Thank you.

React Native Switch not animating when using React Navigation

I am trying to add a Switch to my App, and its animation is not working. I tried to create a Snack and noticed that it works without navigation (see this snack) but doesn't work when it is inside a Screen (see this snack).
It seems to be a problem just in Android.
The Switch code is just it:
const MySwitch = () => {
const [value, setValue] = React.useState(false);
return <Switch value={value} onValueChange={setValue} />;
};
Am I doing something wrong? Is it a problem with Expo, React Navigation or Switch?
In the worst case, how can I animate the component on my own?
Current behavior / Expected behavior:
React Navigation versions:
"#react-navigation/native": "^5.7.2",
"#react-navigation/bottom-tabs": "^5.7.2",
came upon this bug as well, exactly as described.
I implement a settings page where if you toggle one option, another toggle option is displayed. The second Toggle does not suffer from this bug, and this is 100% consistent. So my guess is that he bug is triggered only for Switch components that are rendered on the initial render pass somehow.
as a workaround for this bug, introducing a small delay of 10ms for rendering Switch completely resolves the issue without visible side effects.
function useDelay(ms: number) {
const [gate, setGate] = useState(false);
useEffect(() => {
setTimeout(() => {
setGate(true);
}, ms);
});
return gate;
}
const delayRender = useDelay(10);
return (
<>
{delayRender && (
<Switch />
)}
</>
);

React Native - 'useNativeDriver' was not specified in modal

I'm building a modal which displays a zoomable image using the library react-native-image-viewer. This is my custom component:
<Modal
animationType="slide"
visible={isVisible}
transparent={true}
>
<ImageViewer imageUrls={images} />
</Modal>
The thing is when I click on the image, the modal shows up and it displays the zoomable image but with this warning message:
Animated: useNativeDriver was not specified. This is a required option and must be explicitly set to true or false
I've been searching a lot and the solutions found where to include something like this:
animatedValue = new Animated.Value(-300);
componentDidMount() {
Animated.timing(this.animatedValue,
{
toValue: 0,
duration: 3000,
useAnimatedDriver: true,
}).start();
}
and including ImageViewer inside an Animated.View component, but I've tried it and I still have the same warning. Any solution?
Thanks in advance
This is because RN team made useNativeDriver as a required property https://github.com/facebook/react-native/commit/5876052615f4858ed5fc32fa3da9b64695974238 and react-native-image-viewer maintainer haven't updated its implementation.

Flatlist scroll position onScroll

I am building a header that animates/hides as the user scrolls down a Flatlist.
Is there any way to find out the scroll position of the Flatlist in pixels?
I'm using react native 0.59.8.
I've tried using onScroll hoping it passes a value to the callback - it doesn't.
I've also tried onScrollBeginDrag, onScrollEndDrag and onMomentumScrollEnd.. None of them provide information of the current scroll position.
onSroll={(info)=>{console.log(info)}
I would expect to get some information about the scroll, but none is passed.
use the code
<FlatList onScroll={this.handleScrollView} />
handleScrollView: function(event: Object) {
this.setState({ scrollPosition: event.nativeEvent.contentOffset.y });
}
its working
onScroll={(r) => console.log(r.nativeEvent.contentOffset.y)}
post your code here if you want to find bug
A Flatlist, as said in the docs, has all the props of a ScrollView, so as answered here,
Add a handler to your FlatList:
<FlatList onScroll={this.handleScroll} />
And then:
handleScroll: function(event) {
console.log(event.nativeEvent.contentOffset.y);
},

How to set fixed position the react native action button on the screen

Can I set the position of react native action button to fixed on a flat list?
I have added an action button but when I scroll the flat list, the action button hides!
Thanks, advance.
You'll want to use the Animated API
First you need to create a Flatlist that you can animate. This is easily done with Animated.createAnimatedComponent():
import { Flatlist, Animated } from 'react-native'
const AnimatedFlatlist = Animated.createAnimatedComponent(Flatlist)
Now in your parent component constructor create a new Animated.Value. This will be the value you use to animate your component to scroll along with your AnimatedFlatlist:
constructor(props) {
super(props)
this.state = { translateY: new Animated.Value(0)}
}
Then wrap the component you want to be fixed in an Animated.View and make sure you add a transform to the component style, passing it the animated value you created :
<Animated.View style={{ transform: [{ translateY: this.state.translateY }]}}>
{YourFixedComponent}
</Animated.View>
Finally, you need to attach an Animated.event to your AnimatedFlatlist. This is done using the onScroll prop:
<AnimatedFlatlist
data={...}
renderItem={...}
keyExtractor={...}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.translateY}}}],
{useNativeDriver: true}
)}
scrollEventThrottle={1}
/>
Now your element with move along with your Flatlist. This is a basic example, and you will probably need to mess with interpolation and CSS positioning to get it exactly as you want it.