Skip to content
This repository was archived by the owner on Aug 19, 2022. It is now read-only.

Trying to wrap a HoC baffles me #921

Closed
TimRJensen opened this issue Aug 24, 2017 · 1 comment
Closed

Trying to wrap a HoC baffles me #921

TimRJensen opened this issue Aug 24, 2017 · 1 comment

Comments

@TimRJensen
Copy link

TimRJensen commented Aug 24, 2017

Hello fellas. Firstly, I'm just a javascript hobbyist. I have no formal coding education nor experience, so I may have done a very common mistake. With that out of the way, here's my issue:

Im trying to create a simple (very simple) fade component. I've done so by making a HoC and then wrapping a span or component passed through props:

import * as React from "react";
import * as ReactDOM from "react-dom";
import { Transition } from "react-transition-group";
import * as Radium from "radium";

/**
 * Simple fade-toggle HOC.
 */
interface Props {
	fadeConfig: {
		duration: number | { in: number, out: number },
		timeout: number,
		easing: string,
		repeat: boolean
	},
	in?: boolean
}

const defaultProps = {
	fadeConfig: {
		timeout: 0,
		easing: "linear",
		repeat: false
	},
	in: true
};

const fadeToggle = Radium.keyframes({
	"@keyframes fade-in": {
		from: { opacity: 0 },
		to: { opacity: 1 }
	},
	"@keyframes fade-out": {
		from: { opacity: 1 },
		to: { opacity: 0 }
	},
	"@keyframes fade-timeout": {}
});

function makeFade(WrappedComponent) {
	//@Radium
	class Fade extends React.Component<Props, { in: boolean }> {
		static displayName = `makeFade(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
		static defaultProps = defaultProps;

		node: any;

		constructor(props: Props) {
			super(props);
			this.state = { in: false };
			this.onDone = this.onDone.bind(this);
		}

		componentDidMount() {
			this.node = ReactDOM.findDOMNode(this);
			this.node.addEventListener("aniamationend", this.onDone, false);
			this.setState({ in: this.props.in })
		}

		componentWillReceiveProps(nextProps: Props) {
			nextProps.in !== this.state.in && this.setState({ in: nextProps.in });
		}

		componentWillUnmount() {
			this.node.removeEventListener("animationend", this.onDone, false);
		}

		onDone(e: AnimationEvent) {
			if (e.animationName === "fade-timeout") this.setState({ in: !this.state.in });
			else if (e.animationName === "fade-out") this.setState({ in: this.props.fadeConfig.repeat });
		}

		render() {
			let { /*style,*/ fadeConfig, ...oldProps } = this.props;
			let config = Object.assign({}, defaultProps.fadeConfig, fadeConfig);
			const animation = {
				entering: `fadeToggle ${typeof config.duration === "object" ? config.duration.in : config.duration}ms ${config.easing} alternate forwards`,
				entered: `${config.timeout - (typeof config.duration === "object" ? config.duration.out : config.duration)}ms`,
				//exiting: `fade-out ${typeof config.duration === "object" ? config.duration.out : config.duration}ms ${config.easing} forwards`
			};

			return <Transition
				in={this.state.in}
				timeout={{
					enter: (typeof config.duration === "object" ? config.duration.in : config.duration),
					exit: (typeof config.duration === "object" ? config.duration.out : config.duration)
				}}>{
					(state) => (
						<WrappedComponent {...oldProps}
							style={{
								animation: `${animation[state]}${""/*style ? ", " + style.animation : ""*/}`,
								animationName: fadeToggle
							}}
						/>
					)
				}
			</Transition>
		}
	};
	return Fade;
}

/**
 * Simple fade-toggle component.
 */
class Fade extends React.Component<{ component?: any } & Props> {
	static defaultProps = {
		component: "span"
	};

	render() {
		let { component: Component, children, ...oldProps } = this.props;
		return <Component {...oldProps}>{children}</Component>
	}
}

function createFade(element, config) {
	return <Fade fadeConfig={config} in={true}>{element}</Fade>;
}

export default Radium(makeFade(test));
export { createFade, makeFade };

Here's the implementation:

import * as React from "react";
import Fade from "../common/fade";

const config = {
        duration: {in: 1000, out: 1000},
        timeout: 10000,
        easing: "linear",
        in: true,
        repeat: true
};

export default class Test extends React.Component {
    render () {
        return <div>
            <Fade fadeConfig={config}>
                Hello World! Ave Terra!
            </Fade>
        </div>        
    };
};

And here's what I am getting from webpack (with hot module reload):

wupsi

I have no clue what I am doing wrong?

@ryan-roemer
Copy link
Member

@TimRJensen -- This should be fixed in modern radium as we can now handle native classes and should be able to wrap anything. Separately, might be this issue #443 ?

At any rate, I'm closing this, but feel free to re-open if you still hit this with a minimal repository that has install + error reproduction steps for us to dive in and figure out what's up. Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants