How to use the useRef hook for setNativeProps in React Native?
As per the docs [1] The value of the ref is kept at ref.current
. So you need to run someRef.current.setNativeProps
.
That said your useEffect
code will have problems because someRef
will be set to null
on your first render when useEffect
is running. You'll have to add someRef.current
to the useEffect
dependencies array so the effect is called whenever someRef
updates and add a condition to not call someRef.current.setNativeProps
when someRef.current
is null
. You may want to skip the entire useEffect
body unless someRef.current
is not null
.
useEffect(() => {
if (!someRef.current) {
return;
}
animation.addListener(({value}) => {
const pos = positionInterpolate(value)
setPosition(pos)
})
const style = [
styles.box,
{
transform: [
{
translateY: position
}
]
}
]
someRef.current.setNativeProps({ style })
}, [someRef.current]) # note the addition of `someRef.current` here so the effect runs again when the ref is set
[1] https://reactjs.org/docs/hooks-reference.html#useref
Related videos on Youtube
Kevvv
Updated on May 26, 2022Comments
-
Kevvv almost 2 years
I'm trying to convert the class component of React Native to a functional component that involves
useRef
. Following is the class component:import React, { Component } from "react"; import { AppRegistry, StyleSheet, Text, View, Animated, TouchableWithoutFeedback } from "react-native"; import { interpolateNumber, interpolateRgb } from "d3-interpolate"; export default class animations extends Component { state = { animation: new Animated.Value(0) }; componentWillMount() { const positionInterpolate = interpolateNumber(0, 200); const colorInterpolate = interpolateRgb("rgb(255,99,71)", "rgb(99,71,255)");; this.state.animation.addListener(({value}) => { const position = positionInterpolate(value); const color = colorInterpolate(value); const style = [ styles.box, { backgroundColor: color, transform: [ {translateY: position} ] } ]; this._view.setNativeProps({ style }); }); } handlePress = () => { Animated.timing(this.state.animation, { toValue: 1, duration: 500, }).start(); } render() { return ( <View style={styles.container}> <TouchableWithoutFeedback onPress={this.handlePress}> <View style={styles.box} ref={view => this._view = view} /> </TouchableWithoutFeedback> </View> ); } }
When I convert to the following functional component, I get the following error:
TypeError that someRef.setNativeProps is not a function. (In 'someRef.setNativeProps({ style: style })', 'someRef.setNativeProps' is undefined)
import React, { useState, useEffect, useRef } from 'react' import { View, Animated, TouchableWithoutFeedback, StyleSheet } from 'react-native' import { interpolateNumber, interpolateRgb, } from 'd3-interpolate' export default d3number = () => { const [animation] = useState(new Animated.Value(1)) const [position, setPosition] = useState() const someRef = useRef(null) const startAnimation = () => { Animated.timing(animation, { toValue: 2, duration: 1500, }).start() } const positionInterpolate = interpolateNumber(0, 300) useEffect(() => { animation.addListener(({value}) => { const pos = positionInterpolate(value) setPosition(pos) }) const style = [ styles.box, { transform: [ { translateY: position } ] } ] someRef.setNativeProps({ style }) // console.log(someRef.setNativeProps) }, []) return ( <View style={styles.container}> <TouchableWithoutFeedback onPress={startAnimation}> <View style={styles.box} ref={someRef} /> </TouchableWithoutFeedback> </View> ) }
Update: this was resolved by including the style within the listener
if (!someRef.current) { return; } animation.addListener(({value}) => { const style = [ styles.box, { transform: [ { translateY: positionInterpolate(value) } ] } ] someRef.current.setNativeProps({ style }) }) // console.log(someRef.setNativeProps) }, [someRef.current])