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 onm ouseMoveRightResize = (event) => {
const dx = event.clientX - x;
x = event.clientX;
width = width dx;
resizeableEle.style.width = `${width}px`;
};
const onm ouseUpRightResize = (event) => {
document.removeEventListener("mousemove", onm ouseMoveRightResize);
};
const onm ouseDownRightResize = (event) => {
x = event.clientX;
resizeableEle.style.left = styles.left;
resizeableEle.style.right = null;
document.addEventListener("mousemove", onm ouseMoveRightResize);
document.addEventListener("mouseup", onm ouseUpRightResize);
};
// Top resize
const onm ouseMoveTopResize = (event) => {
const dy = event.clientY - y;
height = height - dy;
y = event.clientY;
resizeableEle.style.height = `${height}px`;
};
const onm ouseUpTopResize = (event) => {
document.removeEventListener("mousemove", onm ouseMoveTopResize);
};
const onm ouseDownTopResize = (event) => {
y = event.clientY;
const styles = window.getComputedStyle(resizeableEle);
resizeableEle.style.bottom = styles.bottom;
resizeableEle.style.top = null;
document.addEventListener("mousemove", onm ouseMoveTopResize);
document.addEventListener("mouseup", onm ouseUpTopResize);
};
// Bottom resize
const onm ouseMoveBottomResize = (event) => {
const dy = event.clientY - y;
height = height dy;
y = event.clientY;
resizeableEle.style.height = `${height}px`;
};
const onm ouseUpBottomResize = (event) => {
document.removeEventListener("mousemove", onm ouseMoveBottomResize);
};
const onm ouseDownBottomResize = (event) => {
y = event.clientY;
const styles = window.getComputedStyle(resizeableEle);
resizeableEle.style.top = styles.top;
resizeableEle.style.bottom = null;
document.addEventListener("mousemove", onm ouseMoveBottomResize);
document.addEventListener("mouseup", onm ouseUpBottomResize);
};
// Left resize
const onm ouseMoveLeftResize = (event) => {
const dx = event.clientX - x;
x = event.clientX;
width = width - dx;
resizeableEle.style.width = `${width}px`;
};
const onm ouseUpLeftResize = (event) => {
document.removeEventListener("mousemove", onm ouseMoveLeftResize);
};
const onm ouseDownLeftResize = (event) => {
x = event.clientX;
resizeableEle.style.right = styles.right;
resizeableEle.style.left = null;
document.addEventListener("mousemove", onm ouseMoveLeftResize);
document.addEventListener("mouseup", onm ouseUpLeftResize);
};
// Add mouse down event listener
const resizerRight = refRight.current;
resizerRight.addEventListener("mousedown", onm ouseDownRightResize);
const resizerTop = refTop.current;
resizerTop.addEventListener("mousedown", onm ouseDownTopResize);
const resizerBottom = refBottom.current;
resizerBottom.addEventListener("mousedown", onm ouseDownBottomResize);
const resizerLeft = refLeft.current;
resizerLeft.addEventListener("mousedown", onm ouseDownLeftResize);
return () => {
resizerRight.removeEventListener("mousedown", onm ouseDownRightResize);
resizerTop.removeEventListener("mousedown", onm ouseDownTopResize);
resizerBottom.removeEventListener("mousedown", onm ouseDownBottomResize);
resizerLeft.removeEventListener("mousedown", onm ouseDownLeftResize);
};
}, []);
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;
}
CodePudding user response:
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'))
CodePudding user response:
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);