@dr.pogodin/react-utils
Version:
Collection of generic ReactJS components and utils
21 lines • 2.56 kB
JavaScript
import{serialize}from"cookie";import{useEffect}from"react";import dayjs from"dayjs";import{DAY_MS,HOUR_MS,MIN_MS,SEC_MS,YEAR_MS,timer}from"@dr.pogodin/js-utils";import{useGlobalState}from"@dr.pogodin/react-global-state";import{getSsrContext}from"./globalState.js";/**
* This react hook wraps Date.now() function in a SSR friendly way,
* ensuring that all calls to useCurrent() within the same render return
* exactly the same time (which is retrieved from Date.now() first, and
* then stored in the global state to be reused in all other calls), which
* is also passed and used in the first client side render, and then updated
* with a finite precision to avoid infinite re-rendering loops.
*/// TODO: Should we request the state type as generic parameter, to be able
// to verify the give globalStatePath is correct?
export function useCurrent({autorefresh=false,globalStatePath="currentTime",precision=5*SEC_MS}={}){const[now,setter]=useGlobalState(globalStatePath,Date.now);useEffect(()=>{let timerId;const update=()=>{setter(old=>{const neu=Date.now();return Math.abs(neu-old)>precision?neu:old});if(autorefresh)timerId=setTimeout(update,precision)};update();return()=>{if(timerId)clearTimeout(timerId)}},[autorefresh,precision,setter]);return now}/**
* Wraps the standard Date.getTimezoneOffset() method in a SSR-friendly way.
* This hook retrieves the offset value at the client side and uses a cookie
* to pass it to the server in subsequent requests from that user. At the server
* side the value from cookie is used in renders and passed back to the client
* via the global state. Prior to the value being known (in the very first
* request from the user, when the cookie is still missing), zero value is used
* as the default value.
*/// TODO: Should we request the state type as generic parameter, to be able
// to verify the give globalStatePath is correct?
export function useTimezoneOffset({cookieName="timezoneOffset",globalStatePath="timezoneOffset"}={}){const ssrContext=getSsrContext(false);const[offset,setOffset]=useGlobalState(globalStatePath,()=>{const value=cookieName&&ssrContext?.req.cookies[cookieName];return value?parseInt(value):0});useEffect(()=>{const date=new Date;const value=date.getTimezoneOffset();setOffset(value);if(cookieName){document.cookie=serialize(cookieName,value.toString(),{path:"/"})}},[cookieName,setOffset]);return offset}const time={DAY_MS,HOUR_MS,MIN_MS,SEC_MS,YEAR_MS,now:Date.now,timer,useCurrent,useTimezoneOffset};export default Object.assign(dayjs,time);
//# sourceMappingURL=time.js.map