I have a react custom component called HomeContent
that accepts some props.
To make that animated as per the react-spring documentation I made
const animatedHomeContent = animated(HomeContent);
Then for rendering I did like this:
<animatedHomeContent
id={1}
avatar="O"
image="..."
image_title="Onion"
title=" Medium Sized Onions"
subtitle="November 08, 2020"
desc="Onions from farms of Nasik"
price="74"
quantity="1kg"
/>
But I see the props are not getting passed. Please tell me how to do it.
It depends on how you want to interact with your component, do you want to use the api or simply supply updated props?
Updating by regenerating the spring
With the first example, using one of the animated native elements (
animated.XXX
) you will rerender the animated wrapper every time you want to update the state, because you will pass it a new, updatedspringProps
object every time you update it, which will cause it to rerender. Or... this is only partially true, the individualSpringValue
's in the returned object will be the same with both methods so if you pass them as individual props, rerendering would theoretically not be necessary but if you pass them as a whole object (whenspringProps
is astyle
object for example) it will be a changed object from last render and cause a rerender of theanimated
wrapper.When you use a custom element that does not take a ref inside the wrapper instead of one of the native elements, the component will rerender once for every animation frame. This is suboptimal from a performance perspective, but with this strategy, you can use whichever api (prop names) you want for your component, much like you have done.
Here is a sandbox with this solution that works: sandbox
You can observe that the animation works but also that the component rerenders a lot.
Updating via the api
If you want to make it more efficient, and use the api for updating your custom component, you need to adhere to a few rules. When you use the api,
react-spring
updates the element via a ref on the corresponding DOM element, and therefore,react-spring
must understand how to update the element without requiring React to rerender it. This implies:forwardRef
doesn't allow you to add multiple refs, changes cannot take place on multiple DOM elements inside your custom component if you want to wrap it inanimated
(there are other strategies to solve this, such as NOT wrapping your component inanimated
and instead use nativeanimated.XXX
elements inside your component and passSpringValue
s as props).react-spring
will not understand how to update this element.Since your element has a lot of custom properties,
react-spring
won't be able to update your component via the api. It will attempt to do so by simply setting the updated properties on the element to which the ref is attached, but since you need React to map the custom properties to the actual properties on the DOM element, this will fail (no DOM element that I know of have the set of properties that you provide).As an example of how to accomplish this, here is a sandbox showing the outlines of this strategy: sandbox
Here you can see that the component renders only once and can still be updated. You can also see that the properties used on the custom component wrapped in
animated
corresponds to props on adiv
element, enablingreact-spring
to do exactly what we want (the children of theAnimatedHomeContent
is a special prop in React namedprops.children
whichreact-spring
knows how to deal with).In the sandbox is also a bad example where other property names are used.
To get a correct behaviour from this version, React has to process the component to map the input props to the native DOM element props. When updating this version via the api,
react-spring
does not rerender the component (since it can take a ref) and instead sets the updated properties on the element to which the ref is attached (inspect the element in the console to see for yourself that these props are set after updating). Since the properties are not real properties, nothing updates or animates on the component.