0

There is a simple drag animation in my 0.62.2 app. The drag was implemented with react-native-gesture-handler 1.6.1 and react-native-reanimated 1.10.1. The dragged item is an image in a square grid. There are 2 grid or 3 grids in a row to display images. Here is the code to render single image in method displayImg:

      const displayImg = (img_source, width, ht, index, modalWidth, modalHt, dataLen, sortFn) => {
       ....
            const dragX = new Value(0);
            const dragY = new Value(0);
            const offsetX = new Value(0);
            const offsetY = new Value(0);
            const addX = add(offsetX, dragX);
            const addY = add(offsetY, dragY);
            const state = new Value(-1);
            const scale = new Value(1);
            const transX = cond(eq(state, State.ACTIVE), addX, set(offsetX, addX));
            const transY = cond(eq(state, State.ACTIVE), addY, [
                                    cond(eq(state, State.END), call([addX, addY, aniIndex, aniGridPR], onUp)),  //<<==onUp is method called after State.END, nothign but a console output for now.
                                    set(offsetY, addY),
                                    ]);
                                    
            const handleGesture = event([
                {
                  nativeEvent: {
                    translationX: dragX,
                    translationY: dragY,
                    state,
                  },
                }, 
              ]);
            
            let aniStyle = {
                transform:[
                    { translateX : transX },
                    { translateY : transY },
                    
                ]
            };
            return (
                <>
                  
                    <PanGestureHandler 
                        onGestureEvent={handleGesture} 
                        onHandlerStateChange={handleGesture}
                        minPointers={1}
                        maxPointers={1}>
                        <Animated.View style={[aniStyle ]}>
                        <GridImage
                            img_source={img_source}
                            width={width}
                            ht={ht}
                            index={index}
                        />
                        </Animated.View>
                    </PanGestureHandler>              

Here is the rendering code to render an image array:

          return (
            <Grid style={{position:"absolute", paddingTop:0,paddingLeft:0}}>
                {pics.map((item, index) => {  //<<==pics is an image array
                    if (index%2===0) {  
                        if (pics[index+1]) {
                            return (
                                <Row style={styles.row}>
                                    {displayImg(picPath(item), screen_width*half, screen_width*half, index,  screen_width, item.height*(screen_width/item.width), len, move)}
                                    {displayImg(picPath(pics[index+1]), screen_width*half, screen_width*half, index+1,  screen_width, pics[index+1].height*(screen_width/pics[index+1].width), len, move)}
                                </Row>    
                            )} else {
                            return (
                                <Row style={styles.row}>
                                    {displayImg(picPath(item), screen_width*half, screen_width*half, index,  screen_width, item.height*(screen_width/item.width), len, move)}
                                </Row>    
                            )};                                           
                    }
                })}                        
            </Grid>
        );

The images can be dragged around. However after a new image is added and cause re-rendering, the previously loaded images can't be dragged and stop responding to drag. However the newly added images still can be dragged. I senses that the problem may be related the code for pan gesture handling and animation but is not able to find out where the problem is. There is post about similar problem but is not exactly the same.

user938363
  • 9,990
  • 38
  • 137
  • 303

1 Answers1

0

The solution is to use useValue to preserve the states of the image component after re-rendering. Since useValue is a hook and can not be used in condition. method displayImg is converted into component DisplayImg and declaration of animated variables are moved to the top in component DisplayImg.

  import Animated, {useValue} from "react-native-reanimated";
  function DisplayImg() {
    const aniIndex= new Value(index);
    const dragX = useValue(0);
    const dragY = useValue(0);
    const offsetX = new Value(0);
    const offsetY = new Value(0);
    var transX = useValue(0);
    var transY = useValue(0);
    const state = new Value(-1);
    const scale = new Value(1);

     ......
  }

As a rule of thumb, all animated value shall useValue to preserve states according to react-native-gesture-handler team.

user938363
  • 9,990
  • 38
  • 137
  • 303