Kartik Fulara
Kartik Fulara

Reputation: 65

Argument of type 'string' is not assignable to parameter of type 'Element'

I am Creating a Project that needs a section to resize when dragging one of the element corner bars, so I searched on Youtube and I found this guy "THE ART OF CODING" he did this feature without importing the packages but he did it in javascript and I am doing it in typescript so this Error is Showing in " Argument of type 'string' is not assignable to parameter of type 'Element "

import React, {
  useRef,
  useEffect
} from "react";
import styles from "./Resize.module.css";

const ResizeableComponents = ({
  children
}: any) => {
  const ref = useRef("#box"); // also try with null so the error : " Argument of type 'null' is not assignable to parameter of type 'Element' "
  const refLeft = useRef("#leftBar");
  const refTop = useRef("#topBar");
  const refRight = useRef("#rightBar");
  const refBottom = useRef("#bottomBar");

  useEffect(() => {
    const resizeableEle = ref.current;
    const styles = window.getComputedStyle(resizeableEle); // " Argument of type 'string' is not assignable to parameter of type 'Element "
    let width = parseInt(styles.width, 10);
    let height = parseInt(styles.height, 10);
    let x = 0;
    let y = 0;

    resizeableEle.style.top = "150px";
    resizeableEle.style.left = "150px";

    // Right resize
    const onMouseMoveRightResize = (event) => {
      const dx = event.clientX - x;
      x = event.clientX;
      width = width + dx;
      resizeableEle.style.width = `${width}px`;
    };

    const onMouseUpRightResize = (event) => {
      document.removeEventListener("mousemove", onMouseMoveRightResize);
    };

    const onMouseDownRightResize = (event) => {
      x = event.clientX;
      resizeableEle.style.left = styles.left;
      resizeableEle.style.right = null;
      document.addEventListener("mousemove", onMouseMoveRightResize);
      document.addEventListener("mouseup", onMouseUpRightResize);
    };

    // Top resize
    const onMouseMoveTopResize = (event) => {
      const dy = event.clientY - y;
      height = height - dy;
      y = event.clientY;
      resizeableEle.style.height = `${height}px`;
    };

    const onMouseUpTopResize = (event) => {
      document.removeEventListener("mousemove", onMouseMoveTopResize);
    };

    const onMouseDownTopResize = (event) => {
      y = event.clientY;
      const styles = window.getComputedStyle(resizeableEle);
      resizeableEle.style.bottom = styles.bottom;
      resizeableEle.style.top = null;
      document.addEventListener("mousemove", onMouseMoveTopResize);
      document.addEventListener("mouseup", onMouseUpTopResize);
    };

    // Bottom resize
    const onMouseMoveBottomResize = (event) => {
      const dy = event.clientY - y;
      height = height + dy;
      y = event.clientY;
      resizeableEle.style.height = `${height}px`;
    };

    const onMouseUpBottomResize = (event) => {
      document.removeEventListener("mousemove", onMouseMoveBottomResize);
    };

    const onMouseDownBottomResize = (event) => {
      y = event.clientY;
      const styles = window.getComputedStyle(resizeableEle);
      resizeableEle.style.top = styles.top;
      resizeableEle.style.bottom = null;
      document.addEventListener("mousemove", onMouseMoveBottomResize);
      document.addEventListener("mouseup", onMouseUpBottomResize);
    };

    // Left resize
    const onMouseMoveLeftResize = (event) => {
      const dx = event.clientX - x;
      x = event.clientX;
      width = width - dx;
      resizeableEle.style.width = `${width}px`;
    };

    const onMouseUpLeftResize = (event) => {
      document.removeEventListener("mousemove", onMouseMoveLeftResize);
    };

    const onMouseDownLeftResize = (event) => {
      x = event.clientX;
      resizeableEle.style.right = styles.right;
      resizeableEle.style.left = null;
      document.addEventListener("mousemove", onMouseMoveLeftResize);
      document.addEventListener("mouseup", onMouseUpLeftResize);
    };

    // Add mouse down event listener
    const resizerRight = refRight.current;
    resizerRight.addEventListener("mousedown", onMouseDownRightResize);
    const resizerTop = refTop.current;
    resizerTop.addEventListener("mousedown", onMouseDownTopResize);
    const resizerBottom = refBottom.current;
    resizerBottom.addEventListener("mousedown", onMouseDownBottomResize);
    const resizerLeft = refLeft.current;
    resizerLeft.addEventListener("mousedown", onMouseDownLeftResize);

    return () => {
      resizerRight.removeEventListener("mousedown", onMouseDownRightResize);
      resizerTop.removeEventListener("mousedown", onMouseDownTopResize);
      resizerBottom.removeEventListener("mousedown", onMouseDownBottomResize);
      resizerLeft.removeEventListener("mousedown", onMouseDownLeftResize);
    };
  }, []);

  return ( <
    div className = {
      styles.container
    } >
    <
    div ref = {
      ref
    }
    id = "box"
    className = {
      styles.resizeable
    } >
    <
    div ref = {
      refLeft
    }
    id = "leftBar"
    className = {
      `${styles.resizer} ${styles.resizerl}`
    } >
    <
    /div> <
    div ref = {
      refTop
    }
    id = "topBar"
    className = {
      `${styles.resizer} ${styles.resizert}`
    } >
    <
    /div> <
    div ref = {
      refRight
    }
    id = "rightBar"
    className = {
      `${styles.resizer} ${styles.resizerr}`
    } >
    <
    /div> <
    div ref = {
      refBottom
    }
    id = "bottomBar"
    className = {
      `${styles.resizer}${styles.resizerb}`
    } >
    <
    /div> < /
    div > <
    /div>
  );
};

export default ResizeableComponents;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Resize.module.css

.container {
    border-radius: 5px;
    width: 100vw;
    height: 100vh;
    background: #FFBC97;
    position: relative;
}

.resizeable {
    position: absolute;
    border: 2px solid #533535;
    width: 100px;
    height: 100px;
    border-radius: 3px;
    display: flex;
    justify-content: center;
    align-items: center;
    min-width: 15px;
    min-height: 15px;
}

.resizer {
    position: absolute;
    background: black;
}

.resizerr {
    cursor: col-resize;
    height: 100%;
    right: 0;
    top: 0;
    width: 5px;
}

.resizert {
    cursor: row-resize;
    height: 5px;
    left: 0;
    top: 0;
    width: 100%;
}

.resizerb {
    cursor: row-resize;
    height: 5px;
    left: 0;
    bottom: 0;
    width: 100%;
}

.resizerl {
    cursor: col-resize;
    height: 100%;
    left: 0;
    top: 0;
    width: 5px;
}

Upvotes: 0

Views: 3414

Answers (2)

Reifocs
Reifocs

Reputation: 746

At first you are assigning ref value to a string, so the type of ref is MutableRefObject<string> which means that ref.current is expected to be a string, what you want is to attach the ref to the dom element on the first render like you did <div ref = {ref}/>, it will then be available in useEffect because it runs after the render. To correct this, explicitly type ref to

const ref= React.useRef<HTMLDivElement>(null);

Upvotes: 2

Robert Rendell
Robert Rendell

Reputation: 2289

I believe this line is the problem:

const ref = useRef("#box");

useRef is just useState but it's not causing a re-render when the value changes. I think you also need something like:

const ref = useRef(document.getElementById('box'))

Upvotes: 0

Related Questions