I'm having a hell of a time trying to get a simple scrolling animation working in react native.
What I'm trying to achieve is that the component scrolls off the right hand edge of the screen after it has been tapped.
Whatever I do with this class, I get the error Attempted to assign to readonly property
when I tap on the element, and I can't figure out why.
The only assignment I can see happening in the animateOut
function is this.anim.offsetX
, but that can't be a readonly property, since I clearly assign to it just fine in the constructor.
Things I've tried, but haven't helped:
Take the animatable value out of the state property, so the animated.timing call isn't trying to directly mutate a state property.
Simplify the animate calls so that there's only one animation ever mutating this value.
Carefully read the example at: the reactjs animation docs and see what I'm doing differently.
look for existing questions on stack overflow. I found this question but the error condition there doesn't seem to apply to my code.
Can someone please show me what I'm doing wrong?
export default class SquareBlock extends Component {
constructor(props) {
super(props);
this.anim = {};
this.anim.offsetX = new Animated.Value(0);
}
animateOut() {
console.log("animating out");
console.log("X offset:",this.anim.offsetX)
Animated.timing(
this.anim.offsetX,
{ toValue: 120,
duration: 500
}
).start();
}
render() {
let content = this.props.content || "Tappable";
let offsetX;
offsetX = this.anim.offsetX;
return (
<Animated.View >
<TouchableNativeFeedback onPress={ () => this.animateOut() }>
<View style={ [styles.outerBox, { "left": offsetX } ] } >
<Text style={ styles.text }> { content }</Text>
</View>
</TouchableNativeFeedback>
</Animated.View>
)
}
}
You have to set the value of X and Y and give it to Animated.View
Moreover, You have to supply a style to animated (atleast style is the name of the prop which animated use).
Try this:
Have a position where you want to start in componentWillMount()
componentWillMount() {
//important
this.position = new Animated.ValueXY({x: 30 , y: 0});
}
In your Animated.View, you have to supply this.position as style //As said, style is the name of the prop which animated take.
<Animated.View style={this.position.getLayout()}> //very important
<TouchableNativeFeedback onPress={ () => this.animateOut() }>
<View style={ [styles.outerBox, { "left": offsetX } ] } >
<Text style={ styles.text }> { content }</Text>
</View>
</TouchableNativeFeedback>
</Animated.View>
and
animateOut() {
this.position ,
Animated.timing(this.position, {
toValue: { x: this.position + 20 , y: 0},
duration: 250
}).start();
}
This should work properly