I am learning how to use ReactJS by making a mock-up personal website. The target design of the homepage is a joystick that, on drag, allows you to select which page you'd like to go to next. There are four buttons, positioned on the top, right, left, and bottom of the central circular GUI.
My idea was, basically: click joystick, drag towards option. If you approach option, it highlights it, and if if you get close enough to the option it navigates you to that page.
I am using framer motion's drag and onDragStart / onDragEnd / onDrag props to try and detect the direction of the drag. Basically, I am getting the dragged element's clientX and clientY position fields (from the event packet emitted by the onDrag functional prop), and comparing it to the dragged element's original clientX and clientY positions. If the change in X is greater than the change in Y, I know that the closest option is on the X-axis, and I can perform some more calculations to figure out whether it's on the left or right side... ditto for the Y axis. I know that these calculations work properly and quickly enough: WITHOUT using any [state, setState] to assign the hover effect to the target div, the script properly indicates and console.logs the correct 'link' it should go to.
The issue is, once I try and use the same code with React's useState function (effectively telling the relevant component to re-render with a hover effect instead of just console.logging the direction), it doesn't work. The hover effect gets stuck on the about page, no matter which direction I try and drag the joystick towards.
Here's some code to show what I'm doing. Again, I started learning React yesterday, so please let me know of any proper practices or more effective ways to do things if you see them.
const linkPaths = {
top: "about",
right: "resume",
bot: "projects",
left: "bots",
};
const Home = () => {
const [isHovering, setIsHovering] = useState(false);
const [joystickIsClicked, setJoystickIsClicked] = useState(false);
const [hoveredLink, setHoveredLink] = useState("");
var draggingTowards = "";
var prevDraggingTowards = "";
var dragStartX, dragStartY;
const joystickWidth = 90;
const outerCircleWidth = 600;
const innerCircleWidth = 550;
return (
<Wrapper>
<Content>
<OuterCircle width={outerCircleWidth} isHovering={isHovering}>
<InnerCircle
width={innerCircleWidth}
isHovering={isHovering}
joystickIsClicked={joystickIsClicked}
>
<JoystickContainer
layout
drag
dragElastic={0}
width={joystickWidth}
dragConstraints={{
top: -innerCircleWidth / 4,
left: -innerCircleWidth / 4,
right: innerCircleWidth / 4,
bottom: innerCircleWidth / 4,
}}
whileHover={{
scale: 1.2,
cursor: "pointer",
backgroundImage:
"linear-gradient(black, black), linear-gradient(to bottom right, cyan, magenta)",
}}
onHoverStart={() => {
setIsHovering(true);
}}
onHoverEnd={() => {
setIsHovering(false);
setJoystickIsClicked(false);
}}
onTapStart={() => {
setJoystickIsClicked(true);
}}
onTap={() => {
setJoystickIsClicked(false);
console.log("finished tap");
}}
onDragStart={(event, info) => {
dragStartX = event.clientX;
dragStartY = event.clientY;
// console.log(`(${dragStartX}, ${dragStartY})`);
}}
onDragEnd={(event, info) => {
// console.log(`(${event.clientX}, ${event.clientY})`);
}}
onDrag={(event, info) => {
if (Math.abs(event.clientX - dragStartX) > Math.abs(event.clientY - dragStartY)) {
// more movement in x direction
if (event.clientX > dragStartX) {
draggingTowards = linkPaths.right;
} else {
draggingTowards = linkPaths.left;
}
}
//more movement in y direction
else {
if (event.clientY > dragStartY) draggingTowards = linkPaths.bot;
else draggingTowards = linkPaths.top;
}
if (draggingTowards !== prevDraggingTowards) {
// only update state function on a change of direction dragging
setHoveredLink(draggingTowards);
prevDraggingTowards = draggingTowards;
}
console.log(hoveredLink);
}}
</JoystickContainer>
</InnerCircle>
</OuterCircle>
</Content>
</Wrapper>
Is there some key thing regarding stateful values and functions in React that I'm missing? I wondered if the re-rendering of the prop was causing issues with the drag, but if that's the case I am unsure how to proceed.
GUI Layout with the effect visible -- dragging direction stuck on "about"