Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Action is being triggered more than once #3

Closed
avishayil opened this issue Jan 15, 2017 · 14 comments
Closed

Action is being triggered more than once #3

avishayil opened this issue Jan 15, 2017 · 14 comments

Comments

@avishayil
Copy link

avishayil commented Jan 15, 2017

                leftContent={leftContent}
                rightContent={rightContent}
                onRightActionComplete={() => {
                    console.log("Right Action Complete");
                }}
                onLeftActionComplete={() => {
                    console.log("Left Action Complete");
                }}

When playing swiping and swiping back while holding the swipeable action open, the action triggers countless times.

When swiping quickly, action triggers twice.

Also, this warning sometimes appear:

Possible Unhandled Promise Rejection (id: 13):
@avishayil
Copy link
Author

Actually, I partly solved it using onRightActionRelease instead of onRightActionComplete, but I still get the warning of possible unhandled promise rejection.

@jshanson7
Copy link
Owner

@avishayil thanks for reporting -- are you on iOS or android? And was it only 'onRightActionComplete' that fired multiple times? Or the left side as well?

@jshanson7
Copy link
Owner

jshanson7 commented Jan 15, 2017

Just added some log statements to the example and the lifecycle callbacks seem to be working correctly for me on iOS:
jan-15-2017 10-48-50
Also tried swiping quickly, but didn't see anything strange.

@jshanson7 jshanson7 reopened this Jan 15, 2017
@avishayil
Copy link
Author

avishayil commented Jan 24, 2017

Maybe i'm doing something wrong here (Ignore the Hebrew), and maybe it's the ListView that causes problems, notice the last part of the GIF:

                leftContent={(
                    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-end', paddingRight: 20, backgroundColor: (this.state.leftActionActivated ? (!appStore.favoriteExists(story.id) ? '#00897b' : '#d32f2f') : '#ffab00') }}>
                        <View style={{ justifyContent: 'center', alignItems: 'center' }}>
                            <Icon name="add-to-favorites" style={{ color: '#ffffff' }} />
                            <Text style={{ color: '#ffffff' }}>{!appStore.favoriteExists(story.id) ? "הוסף למועדפים" : "הסר מהמועדפים"}</Text>
                        </View>
                    </View>
                )}
                onLeftActionActivate={() => this.setState({ leftActionActivated: true })}
                onLeftActionDeactivate={() => this.setState({ leftActionActivated: false })}
                leftActionActivationDistance={200}
                onLeftActionRelease={() => {
                    !appStore.favoriteExists(story.id) ? appStore.add(story.id) : appStore.remove(story.id);
                    this.swipeable.recenter();
                    this.setState({ toggle: !this.state.toggle });
                } }

image

@jshanson7
Copy link
Owner

Hmm the this.swipeable.recenter(); is unnecessary in onLeftActionRelease as it should recenter itself automatically on release -- the recenter method is for recentering programmatically when buttons are exposed.

The gif looks pretty choppy (maybe log statements?), so it's hard to tell what's going on. onLeftActionRelease is fired right when you let go of the row, so you'll see your row flash red while it's sliding back to center. If you don't want to see that color change as it's transitioning, you can change it to onLeftActionComplete and it will wait until it's done transitioning to toggle the appStore favorite. I would try playing with it a bit with debug=false to get a feel of how it will really behave.

@indesignlatam
Copy link

Hi, im having a similar issue even using onRightActionRelease. It seams to be that if a vertical scroll is made while swiping it triggers onRightActionRelease.

I dont remember if native components for iOS when swiping allow to scroll vertically, but that seems to be the way to solve this.

@jshanson7
Copy link
Owner

Interesting, @indesignlatam is there any way you can reproduce this with some sample code that I can run in my simulator? The Swipeable component should prevent vertical scrolling by becoming the pan responder once you've swiped horizontally past the swipeStartMinDistance threshold. Are you using a custom ListView/ScrollView?

@indesignlatam
Copy link

Hi @jshanson7, im using the the List component of Native Base and the MeteorComplexListView of the react-native-meteor package. Is there something I should do to make it work?

@jshanson7
Copy link
Owner

@indesignlatam @avishayil I figured out the problem -- you need to set scrollEnabled={!isSwiping} on your ScrollView, or else Swipeable and your ScrollView will quickly alternate as the pan responder, causing all kinds of issues (see facebook/react-native#1046).

<ScrollView scrollEnabled={!this.state.isSwiping}>
  <Swipeable
    onSwipeStart={() => this.setState({isSwiping: true})}
    onSwipeRelease={() => this.setState({isSwiping: false})}
  </Swipeable>
</ScrollView>

See also: http://browniefed.com/blog/react-native-pan-responder-inside-of-a-scrollview/

@jshanson7
Copy link
Owner

Open to good ways to detect/prevent this within the Swipeable component. I'd prefer not to release a customized ScrollView/ListView and force people to use that. For the time being I will add a ScrollView example and make a note of this issue in the Readme.

@indesignlatam
Copy link

Great, I think adding this to the documentation is enough to start.

I dont know of a way to set the parent props or state without a callback, if that is not possible the only thing that I can think of is a prop that returns the isSwiping state of the Swiper so that there is only 1 callback to pass as a prop.

<ScrollView scrollEnabled={ !this.state.isSwiping }>
  <Swipeable
    onSwipe={ (isSwiping) => this.setState({ isSwiping }) }>
  </Swipeable>
</ScrollView>

@jean-ben-guigui
Copy link

Hello,

I encountered the same problem: my action is being triggered countless times when I swipe vertically while swiping horizontally. So I implemented @jshanson7's solution.
Nevertheless there are still problems with this solution:

  • The swipe takes a bit of time to start because the setState makes the scrollView rerender, .
  • If you swipe diagonally (and quickly), the action is being triggered many times.

What could be done to solve these problems?
Thanks in advance

@sungsong88
Copy link

I hate to say this, but I had to switch over to https://github.com/jemise111/react-native-swipe-list-view because of this issue. When I swipe diagonally, the actions were still triggered(and bad user experience...) I stopped trying to figure out the work around. Too much of headache...

@kopax
Copy link

kopax commented Feb 8, 2020

This is not fixed, I have tried with :

<ScrollView scrollEnabled={!this.state.isSwiping}>
  <Swipeable
    onSwipeStart={() => this.setState({isSwiping: true})}
    onSwipeRelease={() => this.setState({isSwiping: false})}
  </Swipeable>
</ScrollView>

after that, I am not able to scroll down on any of my devices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants