const useAnimationFrame = (fn: () => void) => {
useEffect(() => {
let currentFrame: number = 0;
const step = () => {
fn();
currentFrame = window.requestAnimationFrame(step);
}
step();
return () => {
window.cancelAnimationFrame(currentFrame);
}
}, [fn]);
}
const socket = openSocket(getEnvVariable('API_URL'));
export const useSocketIOClient = () => socket;
import openSocket from 'socket.io-client';
import { getEnvVariable } from '@utils/envs';
interface Events {
loadRealtime: components['schemas']['RouteDto'][];
pointFromClient: components['schemas']['RealtimeGpsSegmentDto'];
newPostUploaded: undefined;
}
export const useSocketIOReceiver = <EventType extends keyof Events, Result extends Events[EventType]>(event: EventType, callback: (data: Result) => void) => {
const socket = useSocketIOClient();
useEffect(() => {
socket.on(event, callback as any);
return () => {
socket.off(event, callback as any)
}
}, [callback, event, socket]);
}
import { useCallback } from 'react';
import { useSocketIOClient } from '@hooks/use-socket-io-client';
interface Events {
join: {
username: string;
activityId: number;
},
leave: string,
}
export const useSocketIOSender = <EventType extends keyof Events, Request extends Events[EventType]>(event: EventType) => {
const socket = useSocketIOClient();
const emit = useCallback((data: Request) => {
socket.emit(event, JSON.stringify(data));
}, [event, socket]);
return { emit };
};
Таймер реального времени с паузой и возможностью менять скорость перемещения по времени
import { useCallback, useRef, useState } from 'react';
import { useMount } from 'react-use';
export const useTimer = (initialTime, initialSpeed = 1) => {
const relativeTime = useRef(initialTime);
const timerStart = useRef(0);
const timerSpeed = useRef(initialSpeed);
const timerIsPaused = useRef(false);
const [timerIsPausedState, setTimerIsPausedState] = useState(false);
const lastPausedTimestamp = useRef(0);
const refreshTimerStart = useCallback(() => timerStart.current = Date.now(), []);
useEffect(() => {
refreshTimerStart();
}, [refreshTimerStart]);
const setTime = useCallback((time: number) => {
refreshTimerStart();
relativeTime.current = time;
lastPausedTimestamp.current = time;
}, [refreshTimerStart]);
const getTime = useCallback(() => {
return relativeTime.current + (Date.now() - timerStart.current) * timerSpeed.current;
}, []);
const setSpeed = useCallback((speed: number) => {
relativeTime.current = getTime();
refreshTimerStart();
timerSpeed.current = speed;
}, [getTime, refreshTimerStart]);
const pause = useCallback(() => {
if (!timerIsPaused.current) {
timerIsPaused.current = true;
setTimerIsPausedState(true);
lastPausedTimestamp.current = getTime();
}
}, [getTime]);
const play = useCallback(() => {
if (timerIsPaused.current) {
timerIsPaused.current = false;
setTimerIsPausedState(false);
setTime(lastPausedTimestamp.current);
}
}, [setTime]);
const getTimeWithPause = useCallback(() => {
if (timerIsPaused.current) return lastPausedTimestamp.current;
return getTime();
}, [getTime]);
const togglePause = useCallback((makePause?: boolean) => {
if (makePause === true) {
pause();
} else if (makePause === false) {
play();
} else {
if (timerIsPaused.current) {
play();
} else {
pause();
}
}
}, [pause, play]);
return { getTime: getTimeWithPause, setTime, setSpeed, togglePause, paused: timerIsPausedState };
};