javascriptreact-motion

Why can't I use curly braces in the body of my Motion callback?


In the simplest example:

import {Motion, spring} from 'react-motion';
// In your render...
<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  {value => <div>{value.x}</div>}
</Motion>

Which works for me, if I put curly braces around the body of the callback thus:

import {Motion, spring} from 'react-motion';
// In your render...
<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  { 
     (value) => { <div>{value.x}</div> }
  }
</Motion>

I get an invariant violation. Am I misunderstanding what is happening here? If I explicitly return the element in the callback, I don't get the invariant violation, but the animation doesn't work.


Solution

  • The Motion component expects a function as its only child, which is what you've provided in both your examples. Motion will call (or render) this function continuously with the updated x value until the animation has finished.

    Now it's up to the provided function to return something React can actually render, i.e. your function should return a valid React element.

    In your first example you are in fact returning a valid element:

    <div>{value.x}</div>
    

    When using JSX, curly braces are for embedding JS expressions, and expressions must resolve to values. But in your second example, you're returning a JS expression that doesn't resolve to anything, it just "contains" an element:

    { <div>{value.x}</div> }
    

    It's basically the equivalent of doing this inside a "normal" render method:

    render() {
      return (
        { <div>Content</div> }
      )
    }
    

    If you for some reason want to wrap it inside curly braces, you'd have to make sure it resolves to something React can render. Or, put in other words, your expression must return a valid React element, e.g:

    {value => {return <div>{value.x}</div>}}