如何使用反应组分类的反应弹簧

问题描述 投票:0回答:1

我试图将react-spring动画库导入一个基于反应组件类的reactjs应用程序。

似乎新的(截至2019年)React Hooks使得一些整合变得更加混乱。

所以这就是为什么我要问如何使用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个回答
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>
    );
  }
}

这是一个带有两个解决方案的codeandbox:https://codesandbox.io/s/8ynxyowzk0

© www.soinside.com 2019 - 2024. All rights reserved.