alexbrillant / react-native-deck-swiper

tinder like react-native deck swiper
ISC License
1.56k stars 465 forks source link

Unable to do asynchronous concatenating #221

Open Siddharth2212 opened 5 years ago

Siddharth2212 commented 5 years ago

Thanks for the awesome library. I am trying to fetch more cards when the cards are almost finished to increase performance. State gets updated with new concatenated cards but the swiper doesn't render new cards. I am attaching code of my component for your reference. Can you please check and suggest what can I do to fix it. This is the code of my file:-

`import React, { Component } from 'react' import Swiper from 'react-native-deck-swiper' import { Button, StyleSheet, Text, View, Image } from 'react-native' import { Card, ListItem, Icon } from 'react-native-elements' import { DataCall } from '../utils/DataCall'; import { Loading } from './LoadingComponent'; import Pure from './PureComponent';

// demo purposes only function * range (start, end) { for (let i = start; i <= end; i++) { yield i } }

class Exemple extends Component { constructor (props) { super(props) this.state = { swipedAllCards: false, swipeDirection: '', cardIndex: 0, cards: [], count: 1 } this.inProgressNetworkReq = false; }

componentWillMount() {
    this.fetchInitialData();
}

componentDidMount(){
    this.mounted = true;
}
async fetchInitialData() {
    //To prevent redundant fetch requests. Needed because cases of quick up/down scroll can trigger onEndReached
    //more than once
    this.inProgressNetworkReq = true;
    const cards = await DataCall.get(this.state.count, this.props.category, 9);
    this.inProgressNetworkReq = false;
    if(cards && this.mounted){
        this.setState({
            cards: this.state.cards.concat(cards),
            count: this.state.count + 1,
        });
    }
}

async fetchMoreData() {
    const cards = await DataCall.get(this.state.count, this.props.category, 9);
    if(cards){
        this.setState({
            cards: this.state.cards.concat(cards)
        })
    }
}

renderCard = (dish, index) => {
    if(dish){
        return (
            <Pure dish={dish} index={index} />
        )
    }
};

onSwiped = (index) => {
    console.log(`on swiped ${index}`)

    if(index==3){
        this.fetchMoreData();
    }
}

onSwipedAllCards = () => {
    this.setState({
        swipedAllCards: true
    })
};

swipeLeft = () => {
    this.swiper.swipeLeft()
};

render () {
    if(this.inProgressNetworkReq){
        return(
            <Loading/>
        )
    }
    else{
        return (
            <View style={styles.container}>
                <Swiper
                    ref={swiper => {
                        this.swiper = swiper
                    }}
                    horizontalSwipe = {false}
                    onSwiped={(index) => this.onSwiped(index)}
                    cards={this.state.cards}
                    cardIndex={this.state.cardIndex}
                    cardVerticalMargin={0}
                    renderCard={this.renderCard}
                    onSwipedAll={this.onSwipedAllCards}
                    stackSize={3}
                    stackSeparation={15}
                    overlayLabels={{
                        bottom: {
                            title: 'BLEAH',
                            style: {
                                label: {
                                    backgroundColor: 'black',
                                    borderColor: 'black',
                                    color: 'white',
                                    borderWidth: 1
                                },
                                wrapper: {
                                    flexDirection: 'column',
                                    alignItems: 'center',
                                    justifyContent: 'center'
                                }
                            }
                        },
                        left: {
                            title: 'NOPE',
                            style: {
                                label: {
                                    backgroundColor: 'black',
                                    borderColor: 'black',
                                    color: 'white',
                                    borderWidth: 1
                                },
                                wrapper: {
                                    flexDirection: 'column',
                                    alignItems: 'flex-end',
                                    justifyContent: 'flex-start',
                                    marginTop: 30,
                                    marginLeft: -30
                                }
                            }
                        },
                        right: {
                            title: 'LIKE',
                            style: {
                                label: {
                                    backgroundColor: 'black',
                                    borderColor: 'black',
                                    color: 'white',
                                    borderWidth: 1
                                },
                                wrapper: {
                                    flexDirection: 'column',
                                    alignItems: 'flex-start',
                                    justifyContent: 'flex-start',
                                    marginTop: 30,
                                    marginLeft: 30
                                }
                            }
                        }
                    }}
                    animateOverlayLabelsOpacity
                    animateCardOpacity
                    swipeBackCard
                >
                </Swiper>
            </View>
        )
    }
}

}

const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F5FCFF' } })

export default Exemple; `

JacobJaffe commented 5 years ago

Also having a similar issue -- In my case, the cards prop is an array of Id's controlled via redux state. I'm using the method suggested in #201 -- updating the cards to be

[...oldCardIds, ...newCardIds]

So that the index is preserved. Where I render the Swiper, I've checked that this array passed to the cards prop has indeed been updated, but the Swiper still only uses the initial cards prop.

Did you figure out a solution for your scenario @Siddharth2212 ?

dochathuc commented 5 years ago

I have integrate this lib to my app. I also have a similar issue because I need to change cards prop. That's why I do some changes on the lib to support cards prop changing. Please remember to keep correct cardIndex also.

https://github.com/dochathuc/react-native-deck-swiper

markhomoki commented 5 years ago

Until v1.5.26, this library had componentWillReceiveProps method, however for some reasons it has been removed. I believe most developers are fetching new cards on swipe therefore a PR would be a better solution for the community instead of a fork. @dochathuc What do you think?

dochathuc commented 5 years ago

Until v1.5.26, this library had componentWillReceiveProps method, however for some reasons it has been removed. I believe most developers are fetching new cards on swipe therefore a PR would be a better solution for the community instead of a fork. @dochathuc What do you think?

@markhomoki Yes, I have just created a fork yesterday. I'll test more with the fork and then create a PR if it is fine.

webraptor commented 5 years ago

Could you guys post how are you updating the cards prop in your parent component? Are you using redux / mobx etc? Adding new cards to the stack is as easy as [...cards, ...filteredNewCards] whereas filteredNewCards is the array containing the new ones to be added to the deck.

webraptor commented 5 years ago

@markhomoki @dochathuc

Until v1.5.26, this library had componentWillReceiveProps method, however for some reasons it has been removed. I believe most developers are fetching new cards on swipe therefore a PR would be a better solution for the community instead of a fork. @dochathuc What do you think?

componentWillReceiveProps was removed because it is deprecated and unsafe If you're still using it in your apps you should not consider upgrading react native to latest versions, as your apps will break. componentWillReceiveProps was initially replaced by getDerivedStateFromProps which was ultimately removed all together because the component doesn't need it.

webraptor commented 5 years ago

@JacobJaffe @Siddharth2212

Also having a similar issue -- In my case, the cards prop is an array of Id's controlled via redux state. I'm using the method suggested in #201 -- updating the cards to be

[...oldCardIds, ...newCardIds]

So that the index is preserved. Where I render the Swiper, I've checked that this array passed to the cards prop has indeed been updated, but the Swiper still only uses the initial cards prop.

Did you figure out a solution for your scenario @Siddharth2212 ?

Please note that the suggestion in #201 was to construct cards as [...cards, ...filteredNewCards] not the card IDs, which seems you're doing: [...oldCardIds, ...newCardIds]

mightym commented 5 years ago

@webraptor is there anything else I have to keep in mind? I'm using redux to update the array of cards and add new cards in my reducer via [...cards, ...newCards]. The render method gets called, I see my new array of cards in the props that get passed to the Swiper component. But the Swiper is not getting updated.

mightym commented 5 years ago

Oh wow. Using the fork of https://github.com/alexbrillant/react-native-deck-swiper/issues/221#issuecomment-475942717 works. You just have to pass in new props into the Swiper and keep track of the cardindex on your own. I'm pretty sure now after hours of trying that the current version of react-native-deck-swiper isn't supporting/handling updating card props on the fly

mightym commented 5 years ago

Double checked my issue. In the current version shouldComponentUpdate receives the new array of cards as props. And also return true but the card stack itself doesn't update. https://github.com/alexbrillant/react-native-deck-swiper/blob/master/Swiper.js#L81