Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion src/hooks/useSelector.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useDebugValue, useRef } from 'react'
import { useCallback, useDebugValue, useId, useRef, useState } from 'react'

import {
createReduxContextHook,
Expand All @@ -11,6 +11,18 @@ import { notInitialized } from '../utils/useSyncExternalStore'

export type CheckFrequency = 'never' | 'once' | 'always'

interface Measure {
duration: number
startTime: number
detail: { loc: string; trace: string; uid: string; code: string }
}
type Loc = string
type Uid = string
const measurements: Record<Loc, Record<Uid, Measure[]>> = {}
// @ts-ignore
// eslint-disable-next-line no-undef
globalThis[Symbol.for('react-redux-selector-measurements')] = measurements

export interface UseSelectorOptions<Selected = unknown> {
equalityFn?: EqualityFn<Selected>
stabilityCheck?: CheckFrequency
Expand Down Expand Up @@ -84,10 +96,31 @@ export function createSelectorHook(context = ReactReduxContext): UseSelector {

const firstRun = useRef(true)

const [trace] = useState<string>(() => {
try {
throw new Error()
} catch (e) {
return e.stack
}
})
const arr = trace.split('\n')
const loc = arr[arr.findIndex((x) => x.startsWith('useSelector')) + 1]
const uid = useId()

const wrappedSelector = useCallback<typeof selector>(
{
[selector.name](state: TState) {
performance.mark('selectorStart')
const selected = selector(state)
performance.mark('selectorEnd')
// @ts-ignore
const measure = performance.measure('selector', {
start: 'selectorStart',
end: 'selectorEnd',
detail: { trace, loc, uid, code: selector.toString() },
}) as any as Measure
;((measurements[loc] ??= {})[uid] ??= []).push(measure)

if (process.env.NODE_ENV !== 'production') {
const finalStabilityCheck =
typeof stabilityCheck === 'undefined'
Expand Down