Я опытный разработчик, но плохо знаком с React и миром javascript. Я пытаюсь создать боковую панель с изменяемым размером в React (см. Полный код и демонстрацию здесь) для личного проекта. Хотя кажется, что это работает, я не уверен, правильно ли это. Вот основная часть кода.
Я хотел бы получить отзывы о:
- Если этот код идиоматически верен? Как использование useEffect, useState и useRef.
- Я не уверен, как
resizeSidebar
функция правильно изменяет размер, несмотря на асинхронный характерsetSidebarWidth
import React from "react";
import { useState, useEffect, useRef } from "react";
import "./App.css";
function App() {
const sidebarRef = useRef(null);
const resizerRef = useRef(null);
const prevX = useRef(null);
const [sidebarWidth, setSidebarWidth] = useState(268);
const [isTracking, setIsTracking] = useState(false);
const resizeSidebar = (mouseMoveEvent) => {
if (prevX && prevX.current) {
let delta = mouseMoveEvent.clientX - prevX.current;
setSidebarWidth(sidebarRef.current.getBoundingClientRect().width + delta);
prevX.current = mouseMoveEvent.clientX;
}
};
const stopResize = (event) => {
window.removeEventListener("mousemove", resizeSidebar);
window.removeEventListener("mouseup", stopResize);
setIsTracking(false);
};
const startResizing = (mouseDownEvent) => {
prevX.current = mouseDownEvent.clientX;
window.addEventListener("mousemove", resizeSidebar);
window.addEventListener("mouseup", stopResize);
};
useEffect(() => {
if (!isTracking) prevX.current = null;
}, [isTracking]);
/*useEffect(() => {
}, [sidebarWidth])*/
useEffect(() => {
const resizer = resizerRef.current;
resizer.addEventListener("mousedown", startResizing);
setIsTracking(true);
}, []);
return (
<div className="app-container">
<div
ref={sidebarRef}
className="app-sidebar"
style={{ width: sidebarWidth }}
>
<div className="app-sidebar-content"></div>
<div ref={resizerRef} className="app-sidebar-resizer"></div>
</div>
<div className="app-frame"></div>
</div>
);
}
export default App;
Вот ссылка на песочницу: https://codesandbox.io/s/react-resizable-sidebar-kz9de