Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add onMouseDown listener via HOC

Hi I've been trying to make a higher order component that adds some state and event listeners to the provided component, so that I can animate them on click/touch via JS. I think I'm pretty far off, it's been a long day so excuse me if this code is nonsense.

import React, { useEffect, useState } from 'react'

const TouchAnimator = (child) => {
      const [animated, setAnimated] = useState(false);
      const [NewComponent, setNewComponent] = useState(child)

      const handleMouseDown = () => {
            setAnimated(true)
      }
      const handleMouseUp = () => {
            setAnimated(false)
      }

      useEffect(() => {
            setNewComponent(React.cloneElement(child, {animated: animated}));
      }, [animated, child])
      return (
            <NewComponent onMouseUp={handleMouseUp} onMouseDown={handleMouseDown}/>
      )
}

export default TouchAnimator

I'm getting an error saying: "Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: <campsite-creatorstyles__CCImageInput />. Did you accidentally export a JSX literal instead of a component?"

Can anyone help me make this work?

like image 434
mattavero Avatar asked Oct 27 '25 07:10

mattavero


1 Answers

First of all, in your example, it isn't HOC

In case using it like this:

<TouchAnimator child={<SomeComponent />} />

Your component can be like:

const TouchAnimator = ({ child }) => {
  const [animated, setAnimated] = useState(false);

  const handleMouseDown = () => {
    setAnimated(true);
  };
  const handleMouseUp = () => {
    setAnimated(false);
  };

  return React.cloneElement(child, {
    onMouseUp: handleMouseUp,
    onMouseDown: handleMouseDown,
    animated
  });
};

But in the example above TouchAnimator is just a React component.

Also, I am not sure about using React.cloneElement. Probably, you can use the next HOC example:

const withTouchAnimator = (WrappedComponent) => {
  return (...props) => {
    const [animated, setAnimated] = useState(false);

    const handleMouseDown = () => {
      setAnimated(true);
    };
    const handleMouseUp = () => {
      setAnimated(false);
    };

    return (
      <WrappedComponent
        {...props}
        animated={animated}
        onMouseDown={handleMouseDown}
        onMouseUp={handleMouseUp}
      />
    );
  };
};

Using the HOC:

const Element = ({ onMouseDown, onMouseUp }) => (
  <div onMouseDown={onMouseDown} onMouseUp={onMouseUp}>
    Element
  </div>
);

const TouchAnimatorExample = withTouchAnimator(Element);

<TouchAnimatorExample />
like image 57
Badyanchik Avatar answered Oct 28 '25 23:10

Badyanchik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!