RoyalLys
RoyalLys

Reputation: 96

Animated element display not updated after position change

I'm fairly new to React-Native, so it's very likely I'm missing some core concepts. I want to create a draggable element and be able to move it back to its original position.

The first part is ok, but when I try to update the position, it looks like it works (because when I click again, the element goes back to its original position), but the view isn't updated.

I tried calling setState and forceUpdate but it doesn't update the view.

Do you guys have any idea why ?

Here is a demo of what I have so far :

import React from 'react';
import {Button, StyleSheet, PanResponder, View, Animated} from 'react-native';

export default class Scene extends React.Component {
    constructor(props) {
        super(props)

        const rectanglePosition = new Animated.ValueXY({ x: 0, y: 0 })
        const rectanglePanResponder = this.createPanResponder();

        this.state = {
            rectanglePosition,
            rectanglePanResponder
        }
    }

    createPanResponder = () => {
        return PanResponder.create({
            onStartShouldSetPanResponder: () => true,
            onPanResponderMove: (event, gesture) => {
                this.state.rectanglePosition.setValue({ x: gesture.dx, y: gesture.dy });
            },
            onPanResponderRelease: () => {
                this.state.rectanglePosition.flattenOffset();
            },
            onPanResponderGrant: () => {
                this.state.rectanglePosition.setOffset({
                    x: this.state.rectanglePosition.x._value,
                    y: this.state.rectanglePosition.y._value
                });
            }
        });
    }

    resetPosition = () => {
        const newPosition = new Animated.ValueXY({ x: 0, y: 0 })

        this.setState({ rectanglePosition: newPosition }) // I thought updating the state triggered a re-render
        this.forceUpdate() // doesn't work either
    }

    getRectanglePositionStyles = () => {
        return {
            top: this.state.rectanglePosition.y._value,
            left: this.state.rectanglePosition.x._value,
            transform: this.state.rectanglePosition.getTranslateTransform()
        }
    }

    render() {
        return (
            <View style={styles.container}>
                <Animated.View 
                    style={[styles.rectangle, this.getRectanglePositionStyles()]}
                    {...this.state.rectanglePanResponder.panHandlers}>
                </Animated.View>

                <View style={styles.footer}>
                    <Button title="Reset" onPress={this.resetPosition}></Button>
                </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        borderColor: 'red',
        backgroundColor: '#F5FCFF',
    },
    footer: {
        borderWidth: 1,
        width: '100%',
        position: 'absolute',
        bottom: 0,
        left: 0,
        backgroundColor: 'blue',
    },
    rectangle: {
        position: 'absolute',
        height: 50,
        width: 50,
        backgroundColor: 'red'
    }
});

Upvotes: 0

Views: 156

Answers (1)

Ziyo
Ziyo

Reputation: 604

If your only intention is to put it on upper left corner:

resetPosition = () => {
  this.state.rectanglePosition.setValue({ x: 0, y: 0 });
};

Note! Refer to this snack to see how you do it without a state https://snack.expo.io/@ziyoshams/stack-overflow

Upvotes: 1

Related Questions