custom div resizing start lagin over time next.js

28 Views Asked by At

this is my code for app with custom window resizing

note.tsx:

import {
  useState,
  useCallback,
  useRef,
  useEffect,
  memo,
  useLayoutEffect,
} from "react";
import Editor from "./editor/editor";
import Preview from "./preview/preview";
import { Container, NoteSection, Resizer } from "./style";
import Header from "./header/header";
import { ViewMode } from "./types";
import { debounce } from "lodash";

interface Props {
  width: string;
}
const Note = memo((props: Props) => {
  const { width } = props;

  const [doc, setDoc] = useState<string>("# Hello, World!\n");
  const [mode, setMode] = useState<ViewMode>(ViewMode.Middle);
  const [editWidth, setEditWidth] = useState("50%");
  const [viewWidth, setViewWidth] = useState("50%");

  const handleDocChange = useCallback((newDoc: string) => {
    setDoc(newDoc);
  }, []);

  const resizerRef = useRef<HTMLDivElement>(null);
  const [isResizing, setIsResizing] = useState(false);

  const handleMouseDown = useCallback(() => {
    setIsResizing(true);
  }, []);

  const handleMouseMove = useCallback(
    debounce((event: MouseEvent) => {
      if (!isResizing) return;
      const resizer = resizerRef.current;
      if (!resizer) return;

      const container = resizer.parentNode as HTMLElement;
      const containerRect = container.getBoundingClientRect();

      const mousePosition = event.clientX - containerRect.left;

      const viewWindowWidth = containerRect.width - mousePosition;

      if (viewWindowWidth > 100 && mousePosition > 100) {
        requestAnimationFrame(() => {
          setEditWidth(mousePosition.toString() + "px");
          setViewWidth(viewWindowWidth.toString() + "px");
        });
      }
    }, 5),
    [isResizing]
  );

  const handleMouseUp = useCallback(() => {
    setIsResizing(false);
  }, []);

  useEffect(() => {
    window.addEventListener("mousemove", handleMouseMove);
    window.addEventListener("mouseup", handleMouseUp);
    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      window.removeEventListener("mouseup", handleMouseUp);
    };
  }, [handleMouseMove]);

  useLayoutEffect(() => {
    if (mode == ViewMode.Middle) {
      setEditWidth(`${editWidth}`);
      setViewWidth(`${viewWidth}`);
    }
  }, [mode]);

  return (
    <NoteSection $width={width}>
      <Header setMode={setMode} mode={mode} width={width} />
      <Container $width={width}>
        <Editor
          onChange={handleDocChange}
          initialDoc={doc}
          mode={mode}
          width={editWidth}
        />
        <Resizer ref={resizerRef} onMouseDown={handleMouseDown} $mode={mode} />
        <Preview doc={doc} mode={mode} width={viewWidth} />
      </Container>
    </NoteSection>
  );
});

export default Note;

page.tsx:

"use client";
import React, { useState, useRef, useCallback, useEffect } from "react";
import Title from "./title/title";
import Note from "./note/note";
import Menu from "./menu/menu";
import { Main, Resizer } from "./style";
import { debounce } from "lodash";

const Home = () => {
  const [menuWidth, setMenuWidth] = useState("197px");

  const resizerRef = useRef<HTMLDivElement>(null);
  const [isResizing, setIsResizing] = useState(false);

  const handleMouseDown = useCallback(() => {
    setIsResizing(true);
  }, []);

  const handleMouseMove = useCallback(
    debounce((event: MouseEvent) => {
      if (!isResizing) return;
      const resizer = resizerRef.current;
      if (!resizer) return;

      const container = resizer.parentNode as HTMLElement;
      const containerRect = container.getBoundingClientRect();

      const mousePosition = event.clientX - containerRect.left;

      let rightWidth = containerRect.width - mousePosition;

      if (rightWidth < (window.innerWidth / 4) * 2.7) {
        rightWidth = (window.innerWidth / 4) * 2.7;
      }
      if (rightWidth > (window.innerWidth / 4) * 2.7 && mousePosition > 100) {
        requestAnimationFrame(() => {
          setMenuWidth((mousePosition - 3).toString() + "px");
        });
      }
    }, 5),
    [isResizing]
  );

  const handleMouseUp = useCallback(() => {
    setIsResizing(false);
  }, []);

  useEffect(() => {
    window.addEventListener("mousemove", handleMouseMove);
    window.addEventListener("mouseup", handleMouseUp);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      window.removeEventListener("mouseup", handleMouseUp);
    };
  }, [handleMouseMove]);

  return (
    <>
      <Title />
      <Main>
        <Menu width={menuWidth} />

        <Note width={menuWidth} />

        <Resizer
          ref={resizerRef}
          onMouseDown={handleMouseDown}
          $width={menuWidth}
        />
      </Main>
    </>
  );
};

export default Home;

page-style.ts:

import styled from "styled-components";

export const Main = styled.main`
  display: flex;
`;

export const Resizer = styled.div<{ $width: string }>`
  position: absolute;
  background: #000;
  width: 3px;
  height: calc(100% - 31px);
  zindex: 1000;
  left: ${(props) => props.$width};
  top: 31px;
  cursor: col-resize;
  margin: 0 0px;
`;

note-style.ts:

import styled from "styled-components";
import { ViewMode } from "./types";

export const NoteSection = styled.div<{ $width: string }>`
  margin-left: ${({ $width }) => $width};
`;

export const Container = styled.div<{ $width: string }>`
  position: absolute;
  top: 56px;
  display: flex;
  width: calc(100% - ${({ $width }) => $width});
  height: calc(100% - 56px);
`;

export const Resizer = styled.div<{ $mode: ViewMode }>`
  background: #000;
  width: 3px;
  cursor: col-resize;
  margin: 0 1px;
  display: ${({ $mode }) => ($mode === ViewMode.Middle ? "block" : "none")};
`;

so when i start app, first minute it works fine, but over time window resizing starts laging and it becomes imposible to resize divs

can be this fixed? i used everything that i was able to found with google and ai

0

There are 0 best solutions below