State.END kept firing
See original GitHub issueI’m trying to implement drag and drop feature using react-native-reanimated + react-native-gesture-handler. Everything is working fine except an event. The problem is an event (State.END) not stop triggering. Here is my code:
import * as React from "react";
import { RecyclerListView, LayoutProvider, DataProvider } from "recyclerlistview";
import Animated from "react-native-reanimated";
import { LayoutChangeEvent, Dimensions } from "react-native";
import { PanGestureHandler, State } from "react-native-gesture-handler";
const { cond, eq, add, call, Value, event, or } = Animated;
interface Props<T> {
rowHeight: number;
data: T[];
indexToKey: (index: number) => string;
renderRow: (
data: T,
index: number,
state: "normal" | "dragging" | "placeholder",
dragHandle: JSX.Element
) => JSX.Element | null;
renderDragHandle: () => JSX.Element;
onSort: (newData: T[]) => void;
}
interface RState {
dataProvider: DataProvider;
dragging: boolean;
draggingIdx: number;
}
function immutableMove(arr, from, to) {
return arr.reduce((prev, current, idx, self) => {
if (from === to) {
prev.push(current);
}
if (idx === from) {
return prev;
}
if (from < to) {
prev.push(current);
}
if (idx === to) {
prev.push(self[from]);
}
if (from > to) {
prev.push(current);
}
return prev;
}, []);
}
export class SortableList<T> extends React.PureComponent<Props<T>, RState> {
list = React.createRef<RecyclerListView<any, any>>();
_layoutProvider: LayoutProvider;
rowCenterY: Animated.Node<number>;
absoluteY = new Value(0);
gestureState = new Value(-1);
onGestureEvent: any;
halfRowHeightValue: Animated.Value<number>;
currIdx = -1;
scrollOffset = 0;
flatlistHeight = 0;
topOffset = 0;
scrolling = false;
constructor(props: Props<T>) {
super(props);
this.halfRowHeightValue = new Value((-props.rowHeight / 2) - 190);
const { width } = Dimensions.get("window");
this.onGestureEvent = event([{
nativeEvent: {
absoluteY: this.absoluteY,
state: this.gestureState
}
}]);
this.rowCenterY = add(this.absoluteY, this.halfRowHeightValue);
this._layoutProvider = new LayoutProvider(
index => {
return 1;
},
(type, dim) => {
dim.width = width;
dim.height = props.rowHeight;
}
);
const dataProvider = new DataProvider((row1, row2) => {
return row1.borrower_id !== row2.borrower_id;
}, props.indexToKey);
this.state = {
dataProvider: dataProvider.cloneWithRows(props.data),
dragging: false,
draggingIdx: -1
};
}
componentDidUpdate(prevProps) {
if (prevProps.data !== this.props.data) {
this.setState({
dataProvider: this.state.dataProvider.cloneWithRows(this.props.data)
});
}
}
handleScroll = (_, __, offsetY: number) => {
this.scrollOffset = offsetY;
};
handleLayout = (e: LayoutChangeEvent) => {
this.flatlistHeight = e.nativeEvent.layout.height;
this.topOffset = 190;
};
yToIndex = (y: number) =>
Math.min(
this.state.dataProvider.getSize() - 1,
Math.max(
0,
Math.floor(
(y + this.scrollOffset - this.topOffset) / this.props.rowHeight
)
)
);
moveList = amount => {
if (!this.scrolling) {
return;
}
this.list.current.scrollToOffset(
this.scrollOffset + amount,
this.scrollOffset + amount,
false
);
requestAnimationFrame(() => {
this.moveList(amount);
});
};
updateOrder = y => {
const newIdx = this.yToIndex(y);
if (this.currIdx !== newIdx) {
this.setState({
dataProvider: this.state.dataProvider.cloneWithRows(
immutableMove(
this.state.dataProvider.getAllData(),
this.currIdx,
newIdx
)
),
draggingIdx: this.yToIndex(y)
});
this.currIdx = newIdx;
}
};
start = ([y]) => {
this.currIdx = this.yToIndex(y);
this.setState({ dragging: true, draggingIdx: this.currIdx });
};
reset = () => {
const newData = this.state.dataProvider.getAllData();
this.setState({
dataProvider: this.state.dataProvider.cloneWithRows(newData),
dragging: false,
draggingIdx: -1
});
this.scrolling = false;
this.currIdx = -1;
console.log('entered');
// this.props.onSort(newData);
};
move = ([y]) => {
if (y + 100 > this.flatlistHeight) {
if (!this.scrolling) {
this.scrolling = true;
this.moveList(20);
}
} else if (y < 100) {
if (!this.scrolling) {
this.scrolling = true;
this.moveList(-20);
}
} else {
this.scrolling = false;
}
this.updateOrder(y);
};
_rowRenderer = (type, data, index) => {
return this.props.renderRow(
data,
index,
this.state.draggingIdx === index ? "placeholder" : "normal",
<PanGestureHandler
maxPointers={1}
onGestureEvent={this.onGestureEvent}
onHandlerStateChange={this.onGestureEvent} >
<Animated.View>{this.props.renderDragHandle()}</Animated.View>
</PanGestureHandler>
);
};
render() {
const { dataProvider, dragging, draggingIdx } = this.state;
return (
<>
<Animated.Code>
{() =>
cond(
eq(this.gestureState, State.BEGAN),
call([this.absoluteY], this.start)
)
}
</Animated.Code>
<Animated.Code>
{() =>
cond(
or(
eq(this.gestureState, State.END),
eq(this.gestureState, State.CANCELLED),
eq(this.gestureState, State.FAILED),
eq(this.gestureState, State.UNDETERMINED)
),
call([], this.reset)
)
}
</Animated.Code>
<Animated.Code>
{() =>
cond(
eq(this.gestureState, State.ACTIVE),
call([this.absoluteY], this.move)
)
}
</Animated.Code>
{dragging ? (
<Animated.View
style={{
top: this.rowCenterY,
position: "absolute",
width: "100%",
zIndex: 99,
elevation: 99
}} >
{this.props.renderRow(
dataProvider.getDataForIndex(draggingIdx),
draggingIdx,
"dragging",
this.props.renderDragHandle()
)}
</Animated.View>
) : null}
<RecyclerListView
ref={this.list}
style={{ flex: 1 }}
onScroll={this.handleScroll}
onLayout={this.handleLayout}
layoutProvider={this._layoutProvider}
dataProvider={dataProvider}
rowRenderer={this._rowRenderer}
extendedState={{ dragging: true }} />
</>
);
}
}
and here is my dependencies:
"dependencies": {
"@react-native-community/async-storage": "^1.7.1",
"@react-native-community/datetimepicker": "^2.1.0",
"@react-native-community/netinfo": "^5.5.0",
"@sendgrid/mail": "^6.4.0",
"native-base": "^2.13.8",
"react": "16.9.0",
"react-native": "0.61.2",
"react-native-gesture-handler": "^1.4.1",
"react-native-linear-gradient": "^2.5.6",
"react-native-loading-spinner-overlay": "^1.0.1",
"react-native-material-dropdown": "^0.11.1",
"react-native-material-menu": "^1.0.0",
"react-native-reanimated": "^1.7.0",
"react-native-screens": "^2.4.0",
"react-native-searchbar": "^1.16.0",
"react-native-vector-icons": "^6.6.0",
"react-navigation": "^4.0.10",
"react-navigation-stack": "^1.9.4",
"realm": "^4.0.0-beta.0",
"recyclerlistview": "^3.0.0"
},
The State.END keep firing the this.reset . Can anyone help me out! Thank you.
Note: (this code working fine in Expo. Seeing this problem on RN Cli, And i’m testing on real android device)
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (1 by maintainers)
Top Results From Across the Web
UPDATE: State court halts firing-squad execution with ...
WASHINGTON (CNS) — South Carolina's Supreme Court has issued a temporary stay blocking the state from executing death-row inmate Richard Moore by firing...
Read more >Wrongful Termination: Was Your Firing Illegal?
Knowing if your firing was legal or illegal can be a complicated issue. Employers usually may fire you at any time but there...
Read more >Governor Newsom and CAL FIRE Announce the End of Peak ...
NAPA – Today, at a fire station in Napa, Governor Gavin Newsom and state fire officials announced the end of peak fire season...
Read more >The American Holiday Tradition of Firing Workers for No ...
There is one irredeemably pinko state where, excepting a probationary period that typically lasts one year, your employer must show cause to get ......
Read more >Fire discipline
Fire discipline is a system of communication in the military, primarily for directing artillery. By definition, fire discipline is the language of fire...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
The same here. It seems that after END handler should switch to UNDETERMINED, but actually he doesn’t.
I will find sometime to do that.