Main technologies in play: FlatList React-Navigation 5 Redux Redux-Thunk.
Main Home page is a Feed of Posts (image, caption, name etc.). Upper right corner of home page is a Header Button that I press to go to the screen where I can create a Post. This is where an image, caption or both would get added to my home page.
Below is my FlatList code for reference. I have already tried to set removeClippedSubviews={false}. Doing so doesn't work and actually makes the problem worse.
<FlatList
ref={flatListRef}
data={allPosts}
extraData={[isLoading, isRefreshing, allPosts]}
refreshControl={
<RefreshControl
refreshing={isRefreshing}
onRefresh={onRefresh}
/>
}
keyExtractor={item => item._id}
initialNumToRender={2}
renderItem={renderItem}
onEndReached={!endOfFeed && !oneTimeLoad && handleLoadMore}
onEndReachedThreshold={2}
ListFooterComponent={renderFooter}
ListHeaderComponent={renderHeader}
removeClippedSubviews={true} // Best way to optimize but sacrifices fast scroll down with blank space
//getItemLayout={(data, index) => ({ length: POST_CARD_HEIGHT, offset: POST_CARD_HEIGHT * index, index})}
//windowSize={20}
//maxToRenderPerBatch={15}
//updateCellsBatchingPeriod={50}
/>
My Stack Navigator is as shown before I press "Submit Post": HomeScreen => CreatePostScreen. Pressing "Submit" in CreatePostScreen dispatches an action that makes an API call to my backend server. Creates the post gets back the created post data including image uri and other metadata and then updates my redux state by prepending the newly created post to the old state.
I then make a call to navigation.pop() bringing me back to HomeScreen. When I see it again I am met with a Post with all relevant data except NO image is showing. I can see it only if I scroll down where it is out of view and then back to it.
Any insights would be helpful.
Sounds like the simple solution would be to use a different navigation method such as navigation.navigate('HomeScreen') or navigation.replace('HomeScreen'). You mentioned that if you scroll down past the post and then back up that the image reloads, so that makes me think using a different navigation might do the trick.
This was an issue related to my backend and how images get uploaded in general.
Because there is an AWSLambda function that converts uploaded images to different sizes for efficiency, popping back to the home feed immediately and trying to grab the just uploaded image resulted in a fail on the image load because it didn't exist yet in its resized format.
The Lambda runs pretty quickly but the state update was occurring faster.
Related
Sorry if this has been asked previously, but I hadn't found a working answer.
I'm currently working on a simple app. The main screen features a vertical flatlist with user generated content. The header, though, is transparent and has a predefined height, so the user can see a background image; when the flatlist is scrolled, it covers this background image, which remains static. The goal is to give the user the feeling that they're covering this image, similar to the pull-up element on google maps, which covers the map to show more data.
This would be a simplified example of the current, working code, so you get the gist of it:
const HomeComponent = () => (
<View>
<ImageBackground source={require('../assets/background.png')}>
<Flatlist
headerComponent={<TransparentHeaderOfPredefinedHeight/>}
data={DATA}
renderItem={renderItem}
keyExtractor={item => item}/>
</ImageBackground>
</View> )
Up until here, everything is fine. The thing is, I would like to add a touchable button on this background, that is subsequently covered when the Flatlist is scrolled.
Here's the issue. I have no way to make the touch event propagate through the flatlist's header and reach this button. I tried using pointerEvents='none' and 'box-only' in different combinations, but whenever I was able to touch that button, I was in turn unable to scroll or to interact with the flatlist elements.
I also tried pushing the background image and button on the flatlist header, and using the vertical offsite of the flatlist scrolling to move these elements and simulate the flatlist scrolling over it. Unfortunately, the result was absolutely atrocious, lacking any kind of smoothness.
Does anyone know how I could implement this functionality? I can provide more info if needed. Thank you in advance!
I need some help. I've made a custom list view with some animation (drag and drop). everything is working fine except when there is large number of data, its taking too much time to load the page/when navigating back from another page. Is there any technique where I can reduce the page loading time? Please do not suggest any external packages, and also I cannot use flatlist either, due to my Animated.Scrollview conflicting with Flatlist own Scrollview. I've searched online, and everyone is using flatlist, which i cannot use. Or is it possible to ignore FlatList Own ScrollView?
Found an alternate solution here. You can use FlatList for larger data. Then pass your Animated.ScrollView component as a props through FlatList.
renderScrollComponent={(props) => (
<Animated.ScrollView
{...props}
onScroll={(event) => {
onScroll({ y: feedScroll })(event)
props.onScroll(event)
}}
/>
)}
I am building an app where I am using Redux and the React-Navigation library. I have a list of workouts in a FlatList:
<FlatList
style={{ backgroundColor: colors.background }}
data={this.props.workoutsList}
renderItem={({ item }) =>
<ListItem workout={item} onPress={() => this.props.navigation.navigate('Workout', item)} />
}
keyExtractor={(item) => item.id}
/>
This shows my list properly, and I can navigate to the specific Workout page for each row I click on, and am provided the attached workout on each click. On this specific workout page, I have an Edit Workout form where users can, for example, update the name and time of the workout.
All of this is no problem...the issue I have comes when I press the back button on the menu that takes me back to the main list of all workouts. The FlatList is still showing the old data and is a source of my problem. It is caching this data so my new saves are not being shown, and as a consequence when I click on the list item again, it attaches the old workout information rather than the newest one I just saved. (hope that makes sense)
I have seen a somewhat similar question: React Navigation: How to update navigation title for parent, when value comes from redux and gets updated in child? but it does not quite encapsulate my main question:
Is it possible where a FlatList can update a specific row from a redux setup, while also maintaining it's scroll position?
I see this working extremely nicely on the Facebook app....as someone is scrolling down their Wall, let's say they click on the item saying "xx Comments". This will navigate the app to a page showing only this post. You can Like/Comment and when you press the back arrow, you are brought back exactly in the scroll position of the Wall you were before AND the number of likes/comments has been update to show your contribution. Is this possible in React Native?
If this is not possible...does anybody know how to at least refresh a page when navigating from a back button in React-Navigation?
EDIT I am open to using another navigation library if there is a better setup somewhere else!
UPDATE
I have attempted several ways to solve this problem, one way I tried was this:
When I made a successful save of the form, I dispatched an action of 'NEEDS_REFRESHING'. This set a redux prop that I picked up on the main FlatList page. In the render of that page, I had an:
if (this.props.needsRefreshing) {
console.log('Needs Refreshing');
this.props.getWorkouts();
}
I was seeing the console, and my FlatList page was properly refreshing (it wasn't bringing me back to the correct scroll position as it just refreshed the main list). but I always got a warning from React Native saying:
Cannot update during an existing state transition (such as within
`render` or another component's constructor). Render methods should be
a pure function of props and state; constructor side-effects are an
anti-pattern, but can be moved to `componentWillMount`.
When I moved this to componentWillMount, the proper refreshing changes were then never getting called and even a console.log in componentWillMount would not show up.
Have you try scrollToIndex(params: object) method? https://facebook.github.io/react-native/docs/flatlist.html#scrolltoindex
And also if you want to update your data inside flatList you should add extraData in Props
https://facebook.github.io/react-native/docs/flatlist.html#extradata
If you use react-navigation goBack() to a screen, that screen will never trigger componentWillMount because this screen never unmount, so please use redux instead.
I would like to remove my "Load more" button from my application and implement a "inifinite-scroll" type of feature, which allows users to scroll up through their message history and download older messages as they're requested.
I'm moving to the FlatList component due to ListView being depricated and I'm trying to figure out a nice implementation for determining when the user has scrolled to the top of the page. Due to the fact that a FlatList always starts at the top of the list, we want to make sure to only call onTopReached when the user is scrolling through the list.
How can I go about this?
Links to open-sourced implementations will be appreciated, but should be listed as a comment and not an answer. Implementations using the ListView are irrelevant.
In this case, you can use refresh control for this purpose.
You can do it similar to this
<FlatList
data={feedList}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
refreshControl={
<RefreshControl refreshing={isloading} onRefresh={this.handleRefresh} />
}
/>
i am troubling using of NavigatorIOS in react native,
<NavigatorIOS
style={styles.navigator}
initialRoute={{
title:'xxx',
component:xxx
}}
navigationBarHidden={true} />
here component xxx is my starting file here i don’t want navigator,after this i am using login screen there also i don’t want navigator after completion of the these screens,I need a navigator in my screen.
for hiding i used above code but to show it in child screen i wrote like this but not showing
this.props.navigator.push({
component:xxxx
title:’xxxx’,
navigationBarHidden:false
})
any help much appreciated
There are a lot of issues when using NavigatorIos. You have 2 options:
Dump NavigatorIos and move to Navigator. I was in the same scenario as you. I was using NavigatorIos and I wanted to completely replace the scene. It was a known issue and since Facebook stopped developing it and moved completely to Navigator, I was pretty much forced to make the change.
Here is more info: Navigator comparison
You can use a custom navigator like this one by Kureev. However, you should take into consideration that the way he implemented it, the navigator bar is part of your view, so when you move to a new scene, the whole page shifts, including your navigator.
I tried both option #1 and #2, and ultimately went with #1 and never looked back. It feels much more native and there is growing support for it.
Hope that helps.