use-combine-values.mjs 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637
  1. import { cancelFrame, frame } from 'motion-dom';
  2. import { useIsomorphicLayoutEffect } from '../utils/use-isomorphic-effect.mjs';
  3. import { useMotionValue } from './use-motion-value.mjs';
  4. function useCombineMotionValues(values, combineValues) {
  5. /**
  6. * Initialise the returned motion value. This remains the same between renders.
  7. */
  8. const value = useMotionValue(combineValues());
  9. /**
  10. * Create a function that will update the template motion value with the latest values.
  11. * This is pre-bound so whenever a motion value updates it can schedule its
  12. * execution in Framesync. If it's already been scheduled it won't be fired twice
  13. * in a single frame.
  14. */
  15. const updateValue = () => value.set(combineValues());
  16. /**
  17. * Synchronously update the motion value with the latest values during the render.
  18. * This ensures that within a React render, the styles applied to the DOM are up-to-date.
  19. */
  20. updateValue();
  21. /**
  22. * Subscribe to all motion values found within the template. Whenever any of them change,
  23. * schedule an update.
  24. */
  25. useIsomorphicLayoutEffect(() => {
  26. const scheduleUpdate = () => frame.preRender(updateValue, false, true);
  27. const subscriptions = values.map((v) => v.on("change", scheduleUpdate));
  28. return () => {
  29. subscriptions.forEach((unsubscribe) => unsubscribe());
  30. cancelFrame(updateValue);
  31. };
  32. });
  33. return value;
  34. }
  35. export { useCombineMotionValues };