(And why should we care.)
Head of Engineering at Vazco
Since 2016 with React on production
Author of github.com/vazco/uniforms
Everything is at radekmie.dev
Happy owner of 10 fingers
Pinch
Pan
Tap
Double tap
Press
Drag and drop
(API)
onAuxClick
, onAuxClickCapture
, onClick
, onClickCapture
, onDoubleClick
, onDoubleClickCapture
, onDrag
, onDragCapture
, onDragEnd
, onDragEndCapture
, onDragEnter
, onDragEnterCapture
, onDragOver
, onDragOverCapture
, onDragStart
, onDragStartCapture
, onDrop
, onDropCapture
, onMouseDown
, onMouseDownCapture
, onMouseEnter
, onMouseLeave
, onMouseMove
, onMouseMoveCapture
, onMouseOut
, onMouseOutCapture
, onMouseUp
, onMouseUpCapture
, onPointerCancel
, onPointerCancelCapture
, onPointerDown
, onPointerDownCapture
, onPointerEnter
, onPointerLeave
, onPointerMove
, onPointerMoveCapture
, onPointerOut
, onPointerOutCapture
, onPointerUp
, onPointerUpCapture
, onScroll
, onScrollCapture
, onTouchCancel
, onTouchCancelCapture
, onTouchEnd
, onTouchEndCapture
, onTouchMove
, onTouchMoveCapture
, onTouchStart
, onTouchStartCapture
, onWheel
, onWheelCapture
export function Room({ room, tables }) {
return (
);
}
Nothing crazy
<svg viewBox={`0 0 ${room.width} ${room.height}`}>
<g>
</g>
</svg>
{room.visuals.map((visual, index) => (
<RoomVisual key={index} visual={visual} />
))}
{tables.map(table => (
<Table table={table} key={table._id} />
))}
export function RoomVisual({ visual }) {
}
Really, nothing special
if (visual.type === 'circ') {
return <circle cx={...} cy={...} r={...} />;
}
if (visual.type === 'rect') {
return <rect height={...} width={...} />;
}
// ...
Actions = functions
import { useState } from 'react';
export function RoomInteractive(props) {
}
Interactions = events
const state = useState(initialRoomState);
const actionsRef = useActions(state, props);
const svgRef = useInteractions(actionsRef, props);
return <Room ref={svgRef} {...} />;
function useActions(state, props) {
}
const actions = {
instances: useRef({}),
onClockClick(reservationId) {
// `props` and `state` are always up-to-date here.
},
onClocksPress(selectedTableModule) {},
onSeatClick(tableId, seatIndex) {}
};
actionsRef.current = actions;
const actionsRef = useRef(actions);
return actionsRef;
Stable reference to functions and instances
function useInteractions(actionsRef, props) {
const svgRef = createRef();
return svgRef;
}
useEffect(() => {
}, [props.room._id]);
import svgPanZoom from 'svg-pan-zoom';
const { instances } = actionsRef.current;
instances.svgElement = svgRef.current;
instances.svgPanZoom = svgPanZoom(svgRef.current, {
customEventsHandler: {
init: () =>
destroy: () =>
},
});
return () => instances.svgPanZoom.destroy();
instances.hammer = initHammer(...),
instances.hammer.destroy(),
function initHammer() {
}
import Hammer from 'hammerjs';
const hammer = new Hammer(svgElement, {
recognizers: [
[Hammer.Pan, { direction: Hammer.DIRECTION_ALL }],
[Hammer.Pinch],
[Hammer.Press],
[Hammer.Tap, { event: 'doubletap', taps: 2 }],
[Hammer.Tap],
],
});
hammer.get('doubletap').recognizeWith('tap');
hammer.get('tap').requireFailure('doubletap');
hammer.on('press', event => /* ... */);
// ...
svg-pan-zoom
handles moving around (panning) and zoomingHammer.js
detects the events and calls our handlersprops
?The event handler doesn't know which component (e.g., table) got clicked exactly
<g data-table={table._id} data-type="table">
...
</g>
const table = event.target.closest('[data-type=table]');
if (!table) { return; }
const tableId = table.dataset.table;
React
!?I
couldn't
care
🥰
less