diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 5a65215b12..f230095a4a 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -140,6 +140,11 @@ function sortSeenPosts(postA: SeenPost, postB: SeenPost): 0 | 1 | -1 {
}
}
+const random1 = Math.random()
+const random2 = Math.random()
+const random3 = Math.random()
+const random4 = Math.random()
+
function useExperimentalSuggestedUsersQuery() {
const {currentAccount} = useSession()
const userActionSnapshot = userActionHistory.useActionHistorySnapshot()
@@ -153,10 +158,10 @@ function useExperimentalSuggestedUsersQuery() {
if (followSuggestions.length > 0) {
suggestedDids = [
// It's ok if these will pick the same item (weighed by its frequency)
- followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
- followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
- followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
- followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
+ followSuggestions[Math.floor(random1 * followSuggestions.length)],
+ followSuggestions[Math.floor(random2 * followSuggestions.length)],
+ followSuggestions[Math.floor(random3 * followSuggestions.length)],
+ followSuggestions[Math.floor(random4 * followSuggestions.length)],
]
}
const seenDids = seen
diff --git a/src/components/ageAssurance/AgeAssuranceInitDialog.tsx b/src/components/ageAssurance/AgeAssuranceInitDialog.tsx
index 2f6c041dc2..cdbc83cb02 100644
--- a/src/components/ageAssurance/AgeAssuranceInitDialog.tsx
+++ b/src/components/ageAssurance/AgeAssuranceInitDialog.tsx
@@ -19,6 +19,7 @@ import {useInitAgeAssurance} from '#/state/ageAssurance/useInitAgeAssurance'
import {logger} from '#/state/ageAssurance/util'
import {useLanguagePrefs} from '#/state/preferences'
import {useSession} from '#/state/session'
+import {useTickEveryMinute} from '#/state/shell'
import {atoms as a, useTheme, web} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge'
@@ -73,10 +74,11 @@ function Inner() {
const getTimeAgo = useGetTimeAgo()
const tlds = useTLDs()
const createSupportLink = useCreateSupportLink()
+ const tick = useTickEveryMinute()
const wasRecentlyInitiated =
lastInitiatedAt &&
- new Date(lastInitiatedAt).getTime() > Date.now() - 5 * 60 * 1000 // 5 minutes
+ new Date(lastInitiatedAt).getTime() > tick - 5 * 60 * 1000 // 5 minutes
const [success, setSuccess] = useState(false)
const [email, setEmail] = useState(currentAccount?.email || '')
diff --git a/src/components/moderation/LabelsOnMeDialog.tsx b/src/components/moderation/LabelsOnMeDialog.tsx
index c817431117..7287858045 100644
--- a/src/components/moderation/LabelsOnMeDialog.tsx
+++ b/src/components/moderation/LabelsOnMeDialog.tsx
@@ -13,6 +13,7 @@ import {sanitizeHandle} from '#/lib/strings/handles'
import {logger} from '#/logger'
import {isAndroid} from '#/platform/detection'
import {useAgent, useSession} from '#/state/session'
+import {useTickEveryMinute} from '#/state/shell'
import * as Toast from '#/view/com/util/Toast'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
@@ -126,6 +127,7 @@ function Label({
? sanitizeHandle(labeler.creator.handle, '@')
: label.src
const timeDiff = useGetTimeAgo({future: true})
+ const tick = useTickEveryMinute()
return (
- Expires in {timeDiff(Date.now(), label.exp)}
+ Expires in {timeDiff(tick, label.exp)}
)}
diff --git a/src/screens/Login/index.tsx b/src/screens/Login/index.tsx
index 9cbbd51216..5c67e3415c 100644
--- a/src/screens/Login/index.tsx
+++ b/src/screens/Login/index.tsx
@@ -38,7 +38,7 @@ const OrderedForms = [
export const Login = ({onPressBack}: {onPressBack: () => void}) => {
const {_} = useLingui()
const failedAttemptCountRef = useRef(0)
- const startTimeRef = useRef(Date.now())
+ const [startTime] = useState(() => Date.now())
const {accounts} = useSession()
const {requestedAccountSwitchTo} = useLoggedOutView()
@@ -118,7 +118,7 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
const onAttemptSuccess = () => {
logEvent('signin:success', {
isUsingCustomProvider: serviceUrl !== DEFAULT_SERVICE,
- timeTakenSeconds: Math.round((Date.now() - startTimeRef.current) / 1000),
+ timeTakenSeconds: Math.round((Date.now() - startTime) / 1000),
failedAttemptsCount: failedAttemptCountRef.current,
})
}
diff --git a/src/screens/Signup/StepCaptcha/CaptchaWebView.tsx b/src/screens/Signup/StepCaptcha/CaptchaWebView.tsx
index f208951d5b..209e747bf6 100644
--- a/src/screens/Signup/StepCaptcha/CaptchaWebView.tsx
+++ b/src/screens/Signup/StepCaptcha/CaptchaWebView.tsx
@@ -1,4 +1,4 @@
-import {useEffect, useMemo, useRef} from 'react'
+import {useEffect, useMemo, useRef, useState} from 'react'
import {WebView, type WebViewNavigation} from 'react-native-webview'
import {type ShouldStartLoadRequest} from 'react-native-webview/lib/WebViewTypes'
@@ -30,7 +30,7 @@ export function CaptchaWebView({
onSuccess: (code: string) => void
onError: (error: unknown) => void
}) {
- const startedAt = useRef(Date.now())
+ const [startedAt] = useState(() => Date.now())
const successTo = useRef(undefined)
useEffect(() => {
@@ -72,7 +72,7 @@ export function CaptchaWebView({
// We want to delay the completion of this screen ever so slightly so that it doesn't appear to be a glitch if it completes too fast
wasSuccessful.current = true
const now = Date.now()
- const timeTaken = now - startedAt.current
+ const timeTaken = now - startedAt
if (timeTaken < MIN_DELAY) {
successTo.current = setTimeout(() => {
onSuccess(code)
diff --git a/src/state/shell/tick-every-minute.tsx b/src/state/shell/tick-every-minute.tsx
index d4978470e5..4d8f539069 100644
--- a/src/state/shell/tick-every-minute.tsx
+++ b/src/state/shell/tick-every-minute.tsx
@@ -6,7 +6,7 @@ const stateContext = React.createContext(0)
stateContext.displayName = 'TickEveryMinuteContext'
export function Provider({children}: React.PropsWithChildren<{}>) {
- const [tick, setTick] = React.useState(Date.now())
+ const [tick, setTick] = React.useState(() => Date.now())
React.useEffect(() => {
const i = setInterval(() => {
setTick(Date.now())
diff --git a/src/view/com/util/LoadingPlaceholder.tsx b/src/view/com/util/LoadingPlaceholder.tsx
index 1b454598b8..e9cbdf4590 100644
--- a/src/view/com/util/LoadingPlaceholder.tsx
+++ b/src/view/com/util/LoadingPlaceholder.tsx
@@ -1,4 +1,4 @@
-import {useMemo} from 'react'
+import {useState} from 'react'
import {
type DimensionValue,
type StyleProp,
@@ -283,7 +283,7 @@ export function ChatListItemLoadingPlaceholder({
style?: StyleProp
}) {
const t = useTheme_NEW()
- const random = useMemo(() => Math.random(), [])
+ const [random] = useState(() => Math.random())
return (