Reputation: 1493
I am using react-spring to try and animate in AJAX content as it is loaded.
I have a container component that I sometimes want to animate to 'auto' from 0 and sometimes I want to animate to 100% depending on a prop that is passed in.
I have a const that I set that is then passed into a calculatedHeight property in the Transition component. I then use this to set the height property in the mounted child component's style property.
const Container = ({ data, children, stretchHeight }) => {
const loaded = data.loadStatus === 'LOADED';
const loading = data.loadStatus === 'LOADING';
const animationHeight = stretchHeight ? '100%' : 'auto';
return (
<div
className={classnames({
'data-container': true,
'is-loading': loading,
'is-loaded': loaded,
'stretch-height': stretchHeight
})}
aria-live="polite"
>
{loading &&
<div style={styles} className='data-container__spinner-wrapper'>
<LoadingSpinner />
</div>
}
<Transition
from={{ opacity: 0, calculatedHeight: 0 }}
enter={{ opacity: 1, calculatedHeight: animationHeight }}
leave={{ opacity: 0, calculatedHeight: 0 }}
config={config.slow}
>
{loaded && (styles => {
return (
<div style={{ opacity: styles.opacity, height: styles.calculatedHeight }}>
{children}
</div>
)
}
)}
</Transition>
</div>
)
}
The problem is that this causes a max callstack exceeded error as I don't think react-spring can understand the '100%' string value, only 'auto'.
Is there a work around for this?
Upvotes: 2
Views: 9409
Reputation: 1
from & to need same unit (number or string)
const [percentage, setPercentage] = useState(100);
// wrong
const animationState2 = useSpring({
from:{width: 0},
to: {width: `${percentage}%`}
});
// right
const animationState2 = useSpring({
from:{width: '0%'},
to: {width: `${percentage}%`}
});
Upvotes: 0
Reputation: 1493
Thanks to @hpalu for helping me realise what the issue was:
The problem is that you switch types, you go from 0 to auto to 0%. It can interpolate auto, but that gets interpolated as a number, you're going to confuse it by mixing that number with a percentage.
To resolve this I created consts for both my start and end points.
const containerHeightAnimationStart = stretchHeight ? '0%' : 0;
const containerHeightAnimationEnd = stretchHeight ? '100%' : 'auto';
I then used these in the animation:
<Transition
native
from={{ opacity: 0, height: containerHeightAnimationStart }}
enter={{ opacity: 1, height: containerHeightAnimationEnd }}
leave={{ opacity: 0, height: containerHeightAnimationStart }}
>
{loaded && (styles => {
return (
<animated.div style={styles}>
{children}
</animated.div>
)
}
)}
</Transition>
Upvotes: 0
Reputation: 1435
The problem is that you switch types, you go from 0 to auto to 0%. It can interpolate auto, but that gets interpolated as a number, you're going to confuse it by mixing that number with a percentage.
PS. Maybe you can trick a little using css: https://codesandbox.io/embed/xolnko178q
Upvotes: 3