Motion: [BUG] SVG animation fails when no initial value set

Created on 19 Jul 2019  Â·  14Comments  Â·  Source: framer/motion

Describe the bug
When I don't define default/initial values _as attributes_, the component fails with the error:

Uncaught TypeError: Cannot read property 'red' of null

To Reproduce
As an example, this component/animation fails. This should be a looping spinner.

const animation = {
  strokeDasharray: ['1px, 200px', '100px, 200px', '100px, 200px'],
  strokeDashoffset: [0, -15, -125],
  transition: { duration: 1.4, ease: 'linear' },
};

const Spinner: FC = (): ReactElement => {
  const controls = useAnimation();

  const handleAnimationComplete = useCallback(() => {
    controls.start(animation);
  }, [controls]);

  useEffect(() => {
    controls.start(animation);
  }, [controls]);

  return (
    <svg viewBox='22 22 44 44'>
      <Circle
        animate={controls}
        onAnimationComplete={handleAnimationComplete}
        cx='44'
        cy='44'
        r='20.2'
        fill='none'
        strokeWidth='3.6'
      />
    </svg>
  );
};

Expected behavior
Modifing the circle to the below works, but this is the only way to resolve the issue. Setting the styles in CSS (with styled-components as an example) does not help.

      <Circle
        animate={controls}
        onAnimationComplete={handleAnimationComplete}
        strokeDasharray='80px, 200px'
        strokeDashoffset='0'
        cx='44'
        cy='44'
        r='20.2'
        fill='none'
        strokeWidth='3.6'
      />

Desktop (please complete the following information):

  • OS: MacOS 10.14.5 (18F132)
  • Browser Version: Chrome 75.0.3770.100 (Official Build) (64-bit)

Additional context
I had the same issue when trying to add a rotate animation to an SVG element. I could not find any workaround for this one, so any help would be greatly appreciated.

const Spinner: FC= (): ReactElement => {
  return (
    <motion.svg viewBox='22 22 44 44' animate={{ rotate: 100 }}>
      <Circle />
    </motion.svg>
  );
};

Other than this, I'm loving Framer Motion - amazing work!

bug in progress

All 14 comments

Thanks for the detailed write-up! I'll take a look at this next week.

Glad you're enjoying it!

Thanks @InventingWithMonster! Let me know if I can help at all.

Ran into the same issue. Also happens when using variants. In my case it happened when trying to animate the <g> tag inside an <svg />

That's because initial~ values for SVGs are read from attributes here. That's certainly not that helpful - would be great to at least have a dev warning for this.

Yes, @Andarist - I also guessed that (which is how I solved the issue for my use case). It would be great to see this improved in some way.

Currently working on this bug but if anyone runs into similar, you can always explicitly set an initial value via the initial prop.

const Spinner = () => (
    <motion.svg viewBox='22 22 44 44' initial={{ rotate: 0 }} animate={{ rotate: 100 }}>
      <Circle />
    </motion.svg>
  )

Thanks @InventingWithMonster, that fix works - but if I use it with some properties, I get an error from react-dom:

Warning: Invalid DOM property `stroke-dasharray`. Did you mean `strokeDasharray`?
    in circle (created by RenderComponent)
    in RenderComponent (created by ForwardRef(MotionComponent))
    in ForwardRef(MotionComponent) (at Spinner.tsx:28)
    in svg (created by RenderComponent)
    in RenderComponent (created by ForwardRef(MotionComponent))
    in ForwardRef(MotionComponent) (at Spinner.tsx:27)
    in div (created by Spinner)
    in Spinner (at Spinner.tsx:24)
    in Spinner (at Spinner.stories.tsx:7)
    in ThemeProvider (at config.jsx:12)

In the DOM, I can see the attribute applied as stroke-dasharray;

initial={{ strokeDasharray: whatever }} comes out as that error?

Yes, sadly. If you aren't seeing that, I can set up a demo for you.

For the record, this is still happening in 1.2.6, although (if I understand correctly) it should have been fixed #221 and released in 1.2.5?

Example: https://codesandbox.io/s/confident-williamson-s09g1

… produces the same originally reported error Uncaught TypeError: Cannot read property 'red' of null

Ah yeah there may still be instances where this occurs. I'm tempted to default unreadable values to 0 - this would work well for the above but it'd break stuff like fill. I'll probably, in cases where we just can't find or infer an initial value, add a warning to ensure you set one.

Yes, I think a meaningful error message would go a long way. I was super-confused about the Cannot read property 'red' of null part and only found out by trial and error how to fix it.

Thanks for this!

I just ran into this today as well! I'm not sure 0 would be the expected here though. I ended up doing this:

const variants = {
  initial: ({ x, y }) => ({
    translateX: x,
    translateY: y,
    opacity: 0
  }),
  animate: ({ x, y }) => ({
    translateX: x,
    translateY: y,
    opacity: 1
  })
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

kevinwolfdev picture kevinwolfdev  Â·  3Comments

rchrdnsh picture rchrdnsh  Â·  3Comments

alex-saunders picture alex-saunders  Â·  3Comments

mulholio picture mulholio  Â·  3Comments

amcdnl picture amcdnl  Â·  3Comments