【问题标题】:How to use react-spring from react component classes如何从反应组件类中使用反应弹簧
【发布时间】:2019-09-18 01:03:47
【问题描述】:

我正在尝试将 react-spring 动画库导入到基于 react 组件类的 reactjs 应用程序中。

似乎新的(截至 2019 年)React Hooks 使集成变得更加混乱。

这就是为什么我要问如何使用 react-spring,而 react-spring 又使用反应钩子,在 ReactJS 应用程序中使用类。

不能正常工作的代码如下:

import React from 'react';
import { useSpring, animated, interpolate } from 'react-spring'


export default class TestAnimation extends React.Component {

    constructor(props) {
        super(props);

        const { o, xyz, color } = useSpring({
            from: { o: 0, xyz: [0, 0, 0], color: 'red' },
            o: 1,
            xyz: [10, 20, 5],
            color: 'green'
        });

        this.aniText = <animated.div
            style={{
                // If you can, use plain animated values like always, ...
                // You would do that in all cases where values "just fit"
                color,
                // Unless you need to interpolate them
                background: o.interpolate(o => `rgba(210, 57, 77, ${o})`),
                // Which works with arrays as well
                transform: xyz.interpolate((x, y, z) => `translate3d(${x}px, ${y}px, ${z}px)`),
                // If you want to combine multiple values use the "interpolate" helper
                border: interpolate([o, color], (o, c) => `${o * 10}px solid ${c}`),
                // You can also form ranges, even chain multiple interpolations
                padding: o.interpolate({ range: [0, 0.5, 1], output: [0, 0, 10] }).interpolate(o => `${o}%`),
                // Interpolating strings (like up-front) through ranges is allowed ...
                borderColor: o.interpolate({ range: [0, 1], output: ['red', '#ffaabb'] }),
                // There's also a shortcut for plain, optionless ranges ...
                opacity: o.interpolate([0.1, 0.2, 0.6, 1], [1, 0.1, 0.5, 1])
            }}
        >
            {o.interpolate(n => n.toFixed(2)) /* innerText interpolation ... */}

        </animated.div>
    };


    render() {
        return <div>
            {this.aniText}
        </div>;
    }
}

导致此错误:

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app

【问题讨论】:

    标签: reactjs react-hooks react-spring


    【解决方案1】:

    你不能在类组件中使用钩子。因此,您可以将动画组件拆分为自己的功能组件,如下所示:

    import React from 'react';
    import { useSpring, animated, interpolate } from 'react-spring'
    
    const AniText = ()=> {
      const { o, xyz, color } = useSpring({
        from: { o: 0, xyz: [0, 0, 0], color: 'red' },
        o: 1,
        xyz: [10, 20, 5],
        color: 'green'
      });
    
      return (<animated.div
        style={{
            // If you can, use plain animated values like always, ...
            // You would do that in all cases where values "just fit"
            color,
            // Unless you need to interpolate them
            background: o.interpolate(o => `rgba(210, 57, 77, ${o})`),
            // Which works with arrays as well
            transform: xyz.interpolate((x, y, z) => `translate3d(${x}px, ${y}px, ${z}px)`),
            // If you want to combine multiple values use the "interpolate" helper
            border: interpolate([o, color], (o, c) => `${o * 10}px solid ${c}`),
            // You can also form ranges, even chain multiple interpolations
            padding: o.interpolate({ range: [0, 0.5, 1], output: [0, 0, 10] }).interpolate(o => `${o}%`),
            // Interpolating strings (like up-front) through ranges is allowed ...
            borderColor: o.interpolate({ range: [0, 1], output: ['red', '#ffaabb'] }),
            // There's also a shortcut for plain, optionless ranges ...
            opacity: o.interpolate([0.1, 0.2, 0.6, 1], [1, 0.1, 0.5, 1])
        }}
      >
        {o.interpolate(n => n.toFixed(2)) /* innerText interpolation ... */}
    
      </animated.div>)
    
    }
    
    export default class TestAnimation extends React.Component {
    
        constructor(props) {
            super(props);
        }
    
        render() {
            return <div>
                <AniText />
            </div>;
        }
    }
    

    或者,如果你想坚持使用类组件,react-spring exports a render-props API 也是如此,这在任何 React 组件、类或其他组件中都是完全有效的:

    import React from "react";
    import { Spring, animated, interpolate } from "react-spring/renderprops";
    
    export default class TestAnimation extends React.Component {
      constructor(props) {
        super(props);
      }
    
      render() {
        return (
          <div>
            <Spring
              native
              from={{ o: 0, xyz: [0, 0, 0], color: "red" }}
              to={{ o: 1, xyz: [10, 20, 5], color: "green" }}
            >
              {({ o, xyz, color }) => (
                <animated.div
                  style={{
                    // If you can, use plain animated values like always, ...
                    // You would do that in all cases where values "just fit"
                    color,
                    // Unless you need to interpolate them
                    background: o.interpolate(o => `rgba(210, 57, 77, ${o})`),
                    // Which works with arrays as well
                    transform: xyz.interpolate(
                      (x, y, z) => `translate3d(${x}px, ${y}px, ${z}px)`
                    ),
                    // If you want to combine multiple values use the "interpolate" helper
                    border: interpolate(
                      [o, color],
                      (o, c) => `${o * 10}px solid ${c}`
                    ),
                    // You can also form ranges, even chain multiple interpolations
                    padding: o
                      .interpolate({ range: [0, 0.5, 1], output: [0, 0, 10] })
                      .interpolate(o => `${o}%`),
                    // There's also a shortcut for plain, optionless ranges ...
                    opacity: o.interpolate([0.1, 0.2, 0.6, 1], [1, 0.1, 0.5, 1])
                  }}
                >
                  {// Finally, this is how you interpolate innerText
                  o.interpolate(n => n.toFixed(2))}
                </animated.div>
              )}
            </Spring>
          </div>
        );
      }
    }
    

    这是一个包含两种解决方案的代码框: https://codesandbox.io/s/8ynxyowzk0

    【讨论】:

      猜你喜欢
      • 2020-08-22
      • 1970-01-01
      • 2018-07-03
      • 2021-08-12
      • 2021-05-09
      • 1970-01-01
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      相关资源
      最近更新 更多