diff --git a/src/components/Cube/Cube.jsx b/src/components/Cube/Cube.jsx
index a7c323b0f78e..b2481cb91420 100644
--- a/src/components/Cube/Cube.jsx
+++ b/src/components/Cube/Cube.jsx
@@ -1,92 +1,43 @@
// Import External Dependencies
import PropTypes from "prop-types";
-import { Component } from "react";
-
-export default class Cube extends Component {
- static propTypes = {
- hover: PropTypes.bool,
- theme: PropTypes.string,
- depth: PropTypes.number,
- repeatDelay: PropTypes.number,
- className: PropTypes.string,
- continuous: PropTypes.bool,
- };
-
- static defaultProps = {
- hover: false,
- theme: "dark",
- depth: 30,
- repeatDelay: 1000,
- };
+import { useEffect, useRef, useState } from "react";
- state = {
- x: 0,
- y: 0,
- z: 0,
- iteration: 0,
- };
+export default function Cube({
+ hover = false,
+ theme = "dark",
+ depth = 30,
+ repeatDelay = 1000,
+ className = "",
+ continuous,
+}) {
+ const [state, setState] = useState({ x: 0, y: 0, z: 0, iteration: 0 });
+ const containerRef = useRef(null);
+ const timeoutRef = useRef(null);
- render() {
- const { x, y, z } = this.state;
- const { theme, depth, className = "" } = this.props;
+ const { x, y, z, iteration } = state;
- return (
-
- (this.container = ref)}
- className={`cube cube--${theme} relative block [transform-style:preserve-3d]`}
- style={{
- width: `${depth}px`,
- paddingBottom: `${depth * 0.5}px`,
- transform: "rotateX(-35.5deg) rotateY(45deg)",
- }}
- >
-
- {this._getFaces("outer")}
-
-
- {this._getFaces("inner")}
-
-
-
- );
- }
-
- componentDidMount() {
- const { hover, continuous, repeatDelay } = this.props;
+ useEffect(() => {
+ const container = containerRef.current;
if (hover) {
- this.container.addEventListener("mouseenter", this._spin);
- this.container.addEventListener("mouseleave", this._reset);
+ const spin = () => {
+ const axes = ["x", "y", "z", "iteration"];
+ const axis = axes[Math.floor(Math.random() * axes.length)];
+ const sign = Math.random() < 0.5 ? -1 : 1;
+ setState((prev) => ({ ...prev, [axis]: sign * 90 }));
+ };
+
+ const reset = () => {
+ setState((prev) => ({ ...prev, x: 0, y: 0, z: 0 }));
+ };
+
+ container.addEventListener("mouseenter", spin);
+ container.addEventListener("mouseleave", reset);
+
+ return () => {
+ container.removeEventListener("mouseenter", spin);
+ container.removeEventListener("mouseleave", reset);
+ };
} else if (continuous) {
let degrees = 0;
const axis = "y";
@@ -94,10 +45,11 @@ export default class Cube extends Component {
const animation = () => {
const obj = {};
obj[axis] = degrees += 90;
- this.setState({
+ setState((prev) => ({
+ ...prev,
...obj,
- iteration: (this.state.iteration + 1) % 4,
- });
+ iteration: (prev.iteration + 1) % 4,
+ }));
// eslint-disable-next-line no-use-before-define
tick();
};
@@ -105,30 +57,13 @@ export default class Cube extends Component {
const tick = () =>
setTimeout(() => requestAnimationFrame(animation), repeatDelay);
- this._timeout = tick();
- }
- }
-
- componentWillUnmount() {
- const { hover, continuous } = this.props;
+ timeoutRef.current = tick();
- if (hover) {
- this.container.removeEventListener("mouseenter", this._spin);
- this.container.removeEventListener("mouseleave", this._reset);
- } else if (continuous) {
- clearTimeout(this._timeout);
+ return () => clearTimeout(timeoutRef.current);
}
- }
-
- /**
- * Get all faces for a cube
- *
- * @param {'inner' | 'outer' } type
- * @return {array} - An array of nodes
- */
- _getFaces(type) {
- const { iteration } = this.state;
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
+ const getFaces = (type) => {
// Keep the thicker border on
// the outside on each iteration
const borderWidthMap = {
@@ -201,50 +136,70 @@ export default class Cube extends Component {
key={i}
className={`cube__face ${baseFaceClasses} ${variantClasses}`}
style={{
- transform: `${rotation} translateZ(${this.props.depth / 2}px)`,
+ transform: `${rotation} translateZ(${depth / 2}px)`,
...borderStyles,
}}
/>
);
});
- }
-
- /**
- * Get a random axis
- *
- * @return {string} - A random axis (i.e. x, y, or z)
- */
- _getRandomAxis() {
- const axes = Object.keys(this.state);
-
- return axes[Math.floor(Math.random() * axes.length)];
- }
-
- /**
- * Spin the cubes in opposite directions semi-randomly
- *
- * @param {object} e - Native event
- */
- _spin = () => {
- const obj = {};
- const axis = this._getRandomAxis();
- const sign = Math.random() < 0.5 ? -1 : 1;
-
- obj[axis] = sign * 90;
-
- this.setState(obj);
};
- /**
- * Rotate the cubes back to their original position
- *
- * @param {object} e - Native event
- */
- _reset = () => {
- this.setState({
- x: 0,
- y: 0,
- z: 0,
- });
- };
+ return (
+
+
+
+ {getFaces("outer")}
+
+
+ {getFaces("inner")}
+
+
+
+ );
}
+
+Cube.propTypes = {
+ hover: PropTypes.bool,
+ theme: PropTypes.string,
+ depth: PropTypes.number,
+ repeatDelay: PropTypes.number,
+ className: PropTypes.string,
+ continuous: PropTypes.bool,
+};