({
value = 0,
unit = 'second',
updateIntervalInSeconds,
...otherProps
})
| 95 | } |
| 96 | |
| 97 | const FormattedRelativeTime: React.FC<Props> = ({ |
| 98 | value = 0, |
| 99 | unit = 'second', |
| 100 | updateIntervalInSeconds, |
| 101 | ...otherProps |
| 102 | }) => { |
| 103 | invariant( |
| 104 | !updateIntervalInSeconds || |
| 105 | !!(updateIntervalInSeconds && canIncrement(unit)), |
| 106 | 'Cannot schedule update with unit longer than hour' |
| 107 | ) |
| 108 | const [prevUnit, setPrevUnit] = React.useState< |
| 109 | Intl.RelativeTimeFormatUnit | undefined |
| 110 | >() |
| 111 | const [prevValue, setPrevValue] = React.useState<number>(0) |
| 112 | const [currentValueInSeconds, setCurrentValueInSeconds] = |
| 113 | React.useState<number>(0) |
| 114 | const updateTimer = React.useRef<number | undefined>(undefined) |
| 115 | |
| 116 | if (unit !== prevUnit || value !== prevValue) { |
| 117 | setPrevValue(value || 0) |
| 118 | setPrevUnit(unit) |
| 119 | setCurrentValueInSeconds( |
| 120 | canIncrement(unit) ? valueToSeconds(value, unit) : 0 |
| 121 | ) |
| 122 | } |
| 123 | |
| 124 | React.useEffect(() => { |
| 125 | function clearUpdateTimer() { |
| 126 | clearTimeout(updateTimer.current) |
| 127 | } |
| 128 | clearUpdateTimer() |
| 129 | // If there's no interval and we cannot increment this unit, do nothing |
| 130 | if (!updateIntervalInSeconds || !canIncrement(unit)) { |
| 131 | return clearUpdateTimer |
| 132 | } |
| 133 | // Figure out the next interesting time |
| 134 | const nextValueInSeconds = currentValueInSeconds - updateIntervalInSeconds |
| 135 | const nextUnit = selectUnit(nextValueInSeconds) |
| 136 | // We've reached the max auto incrementable unit, don't schedule another update |
| 137 | if (nextUnit === 'day') { |
| 138 | return clearUpdateTimer |
| 139 | } |
| 140 | |
| 141 | const unitDuration = getDurationInSeconds(nextUnit) |
| 142 | const remainder = nextValueInSeconds % unitDuration |
| 143 | const prevInterestingValueInSeconds = nextValueInSeconds - remainder |
| 144 | const nextInterestingValueInSeconds = |
| 145 | prevInterestingValueInSeconds >= currentValueInSeconds |
| 146 | ? prevInterestingValueInSeconds - unitDuration |
| 147 | : prevInterestingValueInSeconds |
| 148 | const delayInSeconds = Math.abs( |
| 149 | nextInterestingValueInSeconds - currentValueInSeconds |
| 150 | ) |
| 151 | |
| 152 | if (currentValueInSeconds !== nextInterestingValueInSeconds) { |
| 153 | updateTimer.current = setTimeout( |
| 154 | () => setCurrentValueInSeconds(nextInterestingValueInSeconds), |
nothing calls this directly
no test coverage detected