flowen
flowen

Reputation: 536

React hooks: referencing the parent of a component

I'm creating a custom mouse cursor per component (e.g. a custom mouse cursor on a figure element). I'm writing a custom hook for this. This is the hook so far:

const useMouseCoords = () => {
  let [coords, setCoords] = useState({ x: 0, y: 0 })

  // I need to calculate the coordinates from the parents offset. Here is where I'm stuck. 
  let offsetParent = parentRef.current.getBoundingClientRect()

  function handleCoords(e) {
    setCoords({
      x: e.clientX - offsetParent.x,
      y: e.clientY - offsetParent.y,
    })
  }

  useEffect(() => {
    if (typeof window === `undefined`) return // escape gatsby build process

    window.addEventListener('mousemove', handleCoords)

    return () => {
      window.removeEventListener('mousemove', handleCoords)
    }
  }, [])

  return coords
}

The mousecursor component is quite simple:

const MouseCursor = (props) => {
  let { x, y } = useMouseCoords()

  return (
    <div
      className="mouse-cursor-button"
      style={{
        transform: `translate(${x}px, ${y}px)`,
      }}
    >
      <div className="mouse-cursor-button__text">Click to play</div>
    </div>
  )
}

Code of course doesn't work but is rather to illustrate what I'm trying to achieve.

So I need the parent of the MouseCursor component to calculate the offset. I'm stuck at the part where I want to reference the parent component. I was hoping I could pass it as an argument to the hook.

So the question is how can I access the parent component in the hook?

Upvotes: 1

Views: 3060

Answers (2)

Tom Finney
Tom Finney

Reputation: 2928

Can you not just pass the ref down like:

function Parent() {
  const ref = useRef()
  return <div ref={ref}><MouseCursor parentRef={ref} /></div>
}

const MouseCursor = (props) => {
  let { x, y } = useMouseCoords(props.parentRef)

  return (
    <div
      className="mouse-cursor-button"
      style={{
        transform: `translate(${x}px, ${y}px)`,
      }}
    >
      <div className="mouse-cursor-button__text">Click to play</div>
    </div>
  )
}

See https://codesandbox.io/s/0y46034oyl?fontsize=14 for example

Upvotes: 3

James Jackson
James Jackson

Reputation: 782

You can have a function in the parent component that interacts with it's state and then the uses its state in the props of the children.

class Parent extends Component{
  constructor(props){
    super(props);
    this.state = {
       x: 0,
       y:0
    };
}
//...
function setCoords(x, y){
  this.setState({
    x: x,
    y: y
  })
}
//...
render(){
  return(
    <Child 
      actions={ {setParentCoords: this.setCoords.bind(this)} }
      x={ this.state.x } 
      y={ this.state.y }
  )
}

Now in your child you have access to props.actions.setParentCoords()

Upvotes: 0

Related Questions