alexandr2006
alexandr2006

Reputation: 25

React, redux and react-motion

In APP:

<FramesCollection>
      <Frames1 speed='1.0' width='auto' zIndex='1' />
      <Frames2 speed='1.2' width='auto' zIndex='1' />
      <Frames3 speed='1.4' width='auto' zIndex='1' />
      <Frames4 speed='1.6' width='auto' zIndex='1' />
      <Frames5 speed='2.0' width='auto' zIndex='4' />
      <Frames6 speed='2.5' width='auto' zIndex='3' />
      <Rails />
</FramesCollection>

In FramesCollection:

    render() {
        const { selectedItem, menuItems } = this.props.bottomMenu
        const col = menuItems.length
        const springSettings = { stiffness: 170, damping: 26 };

        return (
            <aside className='frames-collection' ref='framesCollection'>

                {React.Children.map(
                    this.props.children,
                    (child, i) => {
                        if ('speed' in child.props) {

                            const width = Math.round(child.props.speed * col * 2000)
                            const style = { width: width, translateX: spring(-width * selectedItem, springSettings) }

                            return <Motion key={i} style={style}>
                                {child}
                            </Motion>

                        } else {
                            return child;
                        }
                    })
                }

            </aside>
        )
    }

The code is compiled without errors, but in the addition of the browser I see 2 errors:

Warning: Failed prop type: Invalid prop children of type object supplied to Motion, expected function. in Motion (created by FramesCollection) in FramesCollection (created by Connect(FramesCollection)) in Connect(FramesCollection) (created by App) in div (created by App) in App (created by Connect(App)) in Connect(App) in div in Provider

And

Uncaught TypeError: this.props.children is not a function at Object.render (Motion.js:235) at ReactCompositeComponent.js:796 at measureLifeCyclePerf (ReactCompositeComponent.js:75) at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:795) at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:822) at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:362) at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258) at Object.mountComponent (ReactReconciler.js:46) at ReactDOMComponent.mountChildren (ReactMultiChild.js:238) at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)

What am I doing wrong?

Upvotes: 0

Views: 370

Answers (1)

user3109607
user3109607

Reputation:

I'm just getting started with this myself but I think your issue may be fairly straightforwrd. When I looked in the documentation it looks like the child element inside Motion needs to be a function.

Translation in my head:

"It doesn't want the child it wants to know what to DO with that child. So the developer just needs to give a function that takes child as an argument and returns that child in an element."

I think all you need to do is change:

{child}

to

{child => <div style={child} />}

in your code above.

From the react-motion docs: https://github.com/chenglou/react-motion#motion-

<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  {interpolatingStyle => <div style={interpolatingStyle} />}
</Motion>

So the JSX function beginning with "interpolatingStyle" would replace "{child}" in your code. When you do that it looks like this bit "style={{x: spring(10)}}" will be interpreted and the calculation it returns becomes the value of "interpolatingStyle". It looks like part of the requirements of the "interpolatingStyle" function is to specify one child element to render (the div) which the interpolated style will apply to.

Again from the docs:

<Motion />
...

- children: (interpolatedStyle: PlainStyle) => ReactElement

Required function.

interpolatedStyle: the interpolated style object passed back to you.    
E.g. if you gave style={{x: spring(10), y: spring(20)}}, you'll
receive as interpolatedStyle, at a certain time, {x: 5.2, y: 12.1},
which you can then apply on your div or something else.

Return: must return one React element to render.

Make sure to check out the docs on the Motion element section. It's a 2 minute read and it's understandable (I struggle with understanding docs quite often).

Motion props:

  • style: required. An Object ** Read this part, seems tricky until you use it.
  • defaultStyle: optional. Maps to numbers. ** Read this part, it's not tricky but it's hard to explain until you try it (like style)
  • children: required. A function (see above)
  • onRest: optional. The callback fired when the animation comes to a rest

Upvotes: 0

Related Questions