Spring's onRest according to docs should be called after all animations stop. This is not the case, it gets called after each animation in chain.
const s = useSpring({
from: { data: 0 },
to: [{ data: 2 }, { data: -2 }, { data: 0 }],
config: {
duration: 2000
},
onRest() {
console.log('onRest');
}
}};
onRest should be called once, after the chain is finished
https://codesandbox.io/s/usespring-onrest-v9-test-97qui (see console output)
react-spring v9.0.0-beta.34react v16.11.0Please try with the latest canary.
Tested 9.0.0-canary.808.11.4be2ac3 and 9.0.0-canary.808.12.11b2708 with same result.
I can actually handle that myself and right now I'm not sure if that's a bug or working-as-intended. If it's the latter, I guess the docs should mention this case
It's working as intended. The onRest prop is inherited by each animation in the chain. You can specify the onRest prop directly in the last props object, like this:
const s = useSpring({
from: { data: 0 },
to: [{ data: 2 }, { data: -2 }, {
data: 0,
onRest() {
console.log('onRest');
}
}],
config: {
duration: 2000
},
}};
I pulled my hair out figuring out why my onRest callback was called multiple times 馃槄
After trying out the latest canary I can confirm that having a parameter to identify that it's called once per animated props is great.
...
onRest({spring}) {
if(spring.key === 'y'){
// do something
}
}
...
Thanks for this great library ! <3
I can confirm that having a parameter to identify that it's called once per animated props is great.
I don't understand. The onRest prop should be called (at most) once per "update", even if you're animating 2+ values (eg: "x" and "y").
Note: In the latest canary, you can also do this:
onRest: {
x: () => console.log('x.onRest'),
y: () => console.log('y.onRest'),
}
Hi,
I'm using [email protected] and am unable to hit onRest on a spring. My code is as follows
const [animateInSpring, setAnimateInSpring] = useSpring(() => ({
active: 100,
config: animateInSpringConfig,
onStart: () => console.log('logomark started'),
onChange: item => console.log('logomark changed', item),
// onRest: item => console.log('logomark ended', item),
onRest: {
active: item => {
console.log('remove slide', item);
// removeSlide();
},
},
}));
React.useEffect(() => {
setAnimateInSpring({ active: animate ? 0 : 100, immediate: !interfaceInitialised });
}, [animate, interfaceInitialised]);
My code always hits onChange, but refuses to hit onStart as well as onRest although the onChange console log shows me my start and end values as expected for those items? I've tried defining a single onRest function to run on every item but that doesn't work either.
Thanks.
I've gotten around the previous issue by using the onChange event instead of onStart and onRest since they only seem to fire temperamentally. They seem to fire if my onChange event is working properly, but don;t fire if there is not onChange event.
I'm also having an issue with the new useTransition hook. My old method of animating pages was by using the hook as follows:
const routeTransitions = useTransition(location, newLocation => newLocation.pathname, {
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 },
unique: true,
onStart: startValues => transitionStarting(startValues),
onRest: endValues => transitionEnded(endValues),
});
As far as I'm aware the new method for useTransition is as follows:
const routeTransitions = useTransition(location, {
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 },
onProps: (values, theSpring) => {
console.log('props values: ', values);
console.log('theSpring values: ', theSpring);
},
onStart: values => { console.log('start values: ', values); transitionStarting(values); },
onChange: values => { console.log('change values: ', values); },
onRest: values => { console.log('end values: ', values); transitionEnded(values); },
});
The way I render my routes is as follows:
{routeTransitions((values, item) => (
<a.div className='routeContainer' style={routeTransitionStyles(values)}>
<Switch location={item}>
{routeComponents}
</Switch>
</a.div>
)}
I can't see a way to access the location pathname and the events are not firing as expected as with the useSpring hook. I used to use the event handlers to trigger a loading screen that would appear on top of the page, and which would hide once the new page had animated in using the actual pathname to identify the screen across functions, but I can;t see a way of accessing that anymore, previously that would be easy through the values passed to the start and the rest event handlers.
Any help would be much appreciated.
@HQ92 Please open an issue for each problem you're having. 1 for the onStart and onRest problem, and 1 for the useTransition problem. Then others can find it easier. Thanks! (and provide a minimal repro, too plz)
I don't understand. The
onRestprop _should_ be called (at most) once per "update", even if you're animating 2+ values (eg: "x" and "y").
Yes, it should, but I imagined, as @burtek thought, that it was called once ALL the animated values have come to an end, not once for each animated values. (Maybe the doc misses a bit here)
Having a parameter holding those values helped me understand what was going on.
Note: In the latest canary, you can also do this:
onRest: { x: () => console.log('x.onRest'), y: () => console.log('y.onRest'), }
Thanks for the heads up. It's definitively cleaner
@HQ92 Please open an issue for each problem you're having. 1 for the
onStartandonRestproblem, and 1 for theuseTransitionproblem. Then others can find it easier. Thanks! (and provide a minimal repro, too plz)
I think I managed to put something together that works. I had read this thread a few days back but it only really clicked today - https://spectrum.chat/react-spring/general/try-the-new-v9-canary-updated-jan-28~c5cad1eb-c6ff-4b40-9a10-76d368c3e404?m=MTU3MjQ0MjY2NTkxMw==.
My updated code that works is now:
const routeTransitions = useTransition(
location,
{
from: { opacity: 0 },
enter: item => ({
opacity: 1,
onStart: {
opacity: () => newPageEntry(item),
},
onRest: () => oldPageLeft(item),
default: true,
}),
leave: item => ({
opacity: 0,
onRest: () => oldPageLeft(item),
default: true,
}),
},
);
I think it's because onRest is not given any values from the useTransition hook? I think onStart only worked once I nested it within the enter and leave objects. The main bit which helped was being able to pass the item object into any of the callback functions as it allowed me access to the pathname. The api is much nicer and cleaner.
I upgraded to get access to inertial objects and being allowed to decay animations with react-use-gesture. It works really nicely together now. Great work! Just need to try and get the new useTrail hook working and see what's changed that has stopped those working as well as trying to get a spring to animate to the closest stop point on release from a drag gesture.
Thanks again!