I have here a subset of my code – it won’t run as is but outlines what I am doing. Essentially I am placing a floormap image on the floor, checking the size and adjusting for scale of physical size to screen size (getScale()
). Then when scale is updated I load the desks to position on that floorplan, passing in the scale. I am also adding the desk to an array of Refs so I can access the div to adjust the border.
Up until this point, everything works and the border is adjusted when I click the desk. But pressing an arrow key and bringing up the keypress function, none of my state variables is populated.
Why not?
const componponent=()=>{
const mapRef = useRef();
const desksRef = useRef([]);
const [mapScale, setMapScale] = useState();
const [desks, setDesks] = useState({ past: [], present: [], future: [] });
const [currentDesk, setDesk] = useState(-1);
const [currentMap, setCurrentMap] = useState(-1);
const [maps, setMaps] = useState({ maps: [] });
const [editMode, setEditMode] = useState(false);
useEffect(() => {
window.addEventListener('resize', updateSize);
window.addEventListener('keydown', keyDown);
return () => {
window.removeEventListener('resize', updateSize);
window.removeEventListener('keydown', keyDown);
}
}, [])
useEffect(() => {
const desks = buildDesks();
setDesks({ ...desks, present: maps.maps[currentMap]?.desks });
setDeskComponents(desks);
}, [editMode])
useEffect(() => {
const desks = buildDesks();
setDesks({ present: maps.maps[currentMap]?.desks });
setDeskComponents(desks);
}, [mapScale]);
const getScale = () => {
const site = maps.maps[currentMap] //the id on the select
if (!site) return;
let map = mapRef.current;
let rect = map?.getBoundingClientRect();
let mapWidth = rect.width;
let mapHeight = rect.height;
let scaleW = (mapWidth && site?.wMM) ? (mapWidth / site.wMM) : 1;
let scaleH = (mapHeight && site?.hMM) ? (mapHeight / site.hMM) : 1;
setMapScale({ height: scaleH, width: scaleW });
}
const buildDesk = (desk, index) => {
const res =
<Desk key={desk.id}
desk={desk}
isEditing={editMode}
desks={desks.present}
scale={mapScale}
deskTypes={deskTypes}
currentDesk={currentDesk}
fns={DeskFns}
ref={el => desksRef.current[index] = el}
index={index}
/>
return res;
}
const buildDesks = () => {
//getScale();
try {
let res = maps.maps[currentMap]?.desks.map((desk, index) => buildDesk(desk, index));
//let res = desks.present.map(desk => buildDesk(desk);
return res
} catch (error) {
console.error('Error building desks:', error);
return null;
}
};
function keyDown(e) {
if (currentDesk > -1 && editMode == true) {
e.preventDefault();
var key = e.key;
const desk = desks.present[currentDesk];
if (editMode == true) {
switch (key) {
case 'ArrowLeft': //left
desk.x -= 5 / mapScale.width;
break;
case 'ArrowUp': //up
desk.y -= 5 / mapScale.height;
break;
case 'ArrowRight': //right
desk.x += 5 / mapScale.width;
break;
case 'ArrowDown'://down
desk.y += 5 / mapScale.height;
break;
default: break;
}
updateDesk(desk);
}
}
}
return <React.Fragment>{deskComponents}</React.Fragment>
}
export const Desk = forwardRef(({ desk, isEditing, scale, deskTypes, fns, index }, ref) => {
//const [rd, setRedraw] = useState(false);
const [scl,] = useState(scale); //used to correct earlier issue - not necessary now
const [rotation, setRotation] = useState(desk?.rotation ?? 0);
const [size, setSize] = useState(() => {
let deskImg = null;
var dImg = deskTypes?.find(dsk => dsk.deskType === desk.deskType);
let top = parseInt(desk.y * scl.height);
const left = parseInt(desk.x * scl.width);
let width = 0;
let height = 0;
try {
if (dImg) {
deskImg = dImg.deskImage;
width = parseInt(dImg.wMM * scl.width);
height = parseInt(dImg.hMM * scl.height);
}
let imgStyle = {
boxSizing: "border-box",
width: `${width}px`,
height: `${height}px`,
}
const url = `data:image/jpeg;base64,${deskImg}`;
return { url: url, style: imgStyle, left: left ?? 0, top: top ?? 0 };
}
catch (ex) {
console.log(ex);
}
return { left: left, top: top };
});
const handleImageClick = (e) => {
e.stopPropagation();
fns.Set_Current(index);
};
return (
//located in a <Draggable container...>
<div >
<img ref={ref}
alt={`X=${size.left} Y=${size.top} ID=${desk.id} Rotation=${rotation}`}
src={size.url}
style={{
...size.style,
position: 'absolute',
transform: `rotate(${rotation}deg)`,
cursor: 'move',
}}
onClick={(e) => handleImageClick(e)} // Ensure clicks are handled
onKeyDown={fns.onKeyDown}
/>
</div>
)
});
As a thought, is this happening because the keydown event is called from the child, so is getting the child state and not the parent where the function is located?