Skip to content

Commit

Permalink
fix: replace unsafe useMemo with useState
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Dec 17, 2024
1 parent 3d5f1d3 commit 6e3e7ab
Show file tree
Hide file tree
Showing 17 changed files with 43 additions and 47 deletions.
4 changes: 2 additions & 2 deletions dev/test-studio/components/panes/debug/DebugPane.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ChevronDownIcon, ChevronRightIcon, ControlsIcon, LinkIcon} from '@sanity/icons'
import {Box, Card, Code, Flex, Stack, Text} from '@sanity/ui'
import type * as React from 'react'
import {useMemo} from 'react'
import {useMemo, useState} from 'react'
import {usePaneRouter, type UserComponent} from 'sanity/structure'

function usePaneChildLinkComponent(props: {
Expand Down Expand Up @@ -48,7 +48,7 @@ export const DebugPane: UserComponent = function DebugPane(props) {
// notice that the ID is only created on mount and should not change between
// subsequent re-renders, therefore this ID will only change when the parent
// component re-renders.
const randomId = useMemo(() => Math.floor(Math.random() * 10000000).toString(16), [])
const [randomId] = useState(() => Math.floor(Math.random() * 10000000).toString(16))

return (
<Box height="fill">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function TestForm(props: TestFormProps) {
},
)
const [focusPath, setFocusPath] = useState<Path>(() => focusPathFromProps || [])
const patchChannel = useMemo(() => createPatchChannel(), [])
const [patchChannel] = useState(() => createPatchChannel())

useGlobalCopyPasteElementHandler({
element: wrapperRef.current,
Expand Down
20 changes: 7 additions & 13 deletions packages/sanity/src/core/components/scroll/scrollContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import {
useContext,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react'
import {ScrollContext} from 'sanity/_singletons'

Expand All @@ -20,8 +20,6 @@ export interface ScrollContainerProps<T extends ElementType>
onScroll?: (event: Event) => () => void
}

const noop = () => undefined

/**
* This provides a utility function for use within Sanity Studios to create scrollable containers
* It also provides a way for components inside a scrollable container to track onScroll on their first parent scroll container
Expand All @@ -41,22 +39,18 @@ export const ScrollContainer = forwardRef(function ScrollContainer<T extends Ele
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)

const parentContext = useContext(ScrollContext)
const childContext = useMemo(() => createPubSub<Event>(), [])
const [childContext] = useState(() => createPubSub<Event>())

useEffect(() => {
if (onScroll) {
// emit scroll events from children
return childContext.subscribe(onScroll)
}
return noop
if (!onScroll) return undefined
// emit scroll events from children
return childContext.subscribe(onScroll)
}, [childContext, onScroll])

useEffect(() => {
if (!parentContext) return undefined
// let events bubble up
if (parentContext) {
return childContext.subscribe(parentContext.publish)
}
return noop
return childContext.subscribe(parentContext.publish)
}, [parentContext, childContext])

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {type ReactNode, useMemo} from 'react'
import {type ReactNode, useMemo, useState} from 'react'
import {SanityCreateConfigContext} from 'sanity/_singletons'

import {useSource} from '../../studio'
Expand All @@ -19,7 +19,7 @@ export function SanityCreateConfigProvider(props: SanityCreateConfigProviderProp
const {children} = props
const {beta} = useSource()

const appIdCache = useMemo(() => createAppIdCache(), [])
const [appIdCache] = useState(() => createAppIdCache())

const value = useMemo((): SanityCreateConfigContextValue => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,13 @@ export function PortableTextInput(props: PortableTextInputProps): ReactNode {
const toast = useToast()

// Memoized patch stream
const patchSubject: Subject<{
patches: EditorPatch[]
snapshot: PortableTextBlock[] | undefined
}> = useMemo(() => new Subject(), [])
const [patchSubject] = useState(
() =>
new Subject<{
patches: EditorPatch[]
snapshot: PortableTextBlock[] | undefined
}>(),
)
const patches$ = useMemo(() => patchSubject.asObservable(), [patchSubject])

const handleToggleFullscreen = useCallback(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {observableCallback} from 'observable-callback'
import {useMemo} from 'react'
import {useMemo, useState} from 'react'
import {useObservable} from 'react-rx'
import {concat, type Observable, of} from 'rxjs'
import {catchError, concatMap, map, startWith} from 'rxjs/operators'
Expand Down Expand Up @@ -34,7 +34,7 @@ export function useReferenceInfo(
getReferenceInfo: GetReferenceInfo,
): Loadable<ReferenceInfo> {
// NOTE: this is a small message queue to handle retries
const [onRetry$, onRetry] = useMemo(() => observableCallback(), [])
const [[onRetry$, onRetry]] = useState(() => observableCallback())

const referenceInfoObservable = useMemo(
() =>
Expand Down
8 changes: 4 additions & 4 deletions packages/sanity/src/core/form/store/useFormState.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable camelcase */

import {type ObjectSchemaType, type Path, type ValidationMarker} from '@sanity/types'
import {useMemo} from 'react'
import {useMemo, useState} from 'react'

import {type FormNodePresence} from '../../presence'
import {useCurrentUser} from '../../store'
Expand Down Expand Up @@ -53,9 +53,9 @@ export function useFormState<
// note: feel free to move these state pieces out of this hook
const currentUser = useCurrentUser()

const prepareHiddenState = useMemo(() => createCallbackResolver({property: 'hidden'}), [])
const prepareReadOnlyState = useMemo(() => createCallbackResolver({property: 'readOnly'}), [])
const prepareFormState = useMemo(() => createPrepareFormState(), [])
const [prepareHiddenState] = useState(() => createCallbackResolver({property: 'hidden'}))
const [prepareReadOnlyState] = useState(() => createCallbackResolver({property: 'readOnly'}))
const [prepareFormState] = useState(() => createPrepareFormState())

const reconcileFieldGroupState = useMemo(() => {
let last: StateTree<string> | undefined
Expand Down
6 changes: 3 additions & 3 deletions packages/sanity/src/core/form/studio/FormBuilder.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import {type SanityClient} from '@sanity/client'
import {defineType, type Path} from '@sanity/types'
import {render} from '@testing-library/react'
import {useMemo} from 'react'
import {useMemo, useState} from 'react'
import {beforeEach, describe, expect, it, type Mock, vi} from 'vitest'

import {createMockSanityClient} from '../../../../test/mocks/mockSanityClient'
Expand Down Expand Up @@ -77,7 +77,7 @@ describe('FormBuilder', () => {
throw new Error('schema type is not an object')
}

const patchChannel = useMemo(() => createPatchChannel(), [])
const [patchChannel] = useState(() => createPatchChannel())

const formState = useFormState({
schemaType,
Expand Down Expand Up @@ -174,7 +174,7 @@ describe('FormBuilder', () => {
throw new Error('schema type is not an object')
}

const patchChannel = useMemo(() => createPatchChannel(), [])
const [patchChannel] = useState(() => createPatchChannel())

const formState = useFormState({
schemaType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {useToast} from '@sanity/ui'
import {getTimeZones} from '@vvo/tzdb'
import {formatInTimeZone, utcToZonedTime, zonedTimeToUtc} from 'date-fns-tz'
import {useCallback, useEffect, useMemo, useState} from 'react'
import {useCallback, useEffect, useState} from 'react'

import ToastDescription from '../components/toastDescription/ToastDescription'
import {DATE_FORMAT, LOCAL_STORAGE_TZ_KEY} from '../constants'
Expand Down Expand Up @@ -55,8 +55,7 @@ function getStoredTimeZone(): NormalizedTimeZone {
}

const useTimeZone = () => {
const initialTimeZone = useMemo(() => getStoredTimeZone(), [])
const [timeZone, setTimeZone] = useState<NormalizedTimeZone>(initialTimeZone)
const [timeZone, setTimeZone] = useState<NormalizedTimeZone>(() => getStoredTimeZone())
const toast = useToast()

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Flex, Stack} from '@sanity/ui'
import {addDays} from 'date-fns'
import {useCallback, useMemo} from 'react'
import {useCallback, useState} from 'react'

import {useTranslation} from '../../../../../../../../../i18n'
import {useSearchState} from '../../../../../contexts/search/useSearchState'
Expand Down Expand Up @@ -29,8 +29,8 @@ export function CommonDateRangeInput({
* For placeholder values: Use the current date for the end date input, and an arbitrary date
* in the past (e.g. -7 days from now) for the start date input.
*/
const placeholderStartDate = useMemo(() => addDays(new Date(), PLACEHOLDER_START_DATE_OFFSET), [])
const placeholderEndDate = useMemo(() => new Date(), [])
const [placeholderStartDate] = useState(() => addDays(new Date(), PLACEHOLDER_START_DATE_OFFSET))
const [placeholderEndDate] = useState(() => new Date())

const handleDatePickerChange = useCallback(
({date, endDate}: {date?: Date | null; endDate?: Date | null}) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {type ObjectSchemaType, type Path} from '@sanity/types'
import {useCallback, useMemo, useRef, useState} from 'react'
import {useCallback, useRef, useState} from 'react'

import {
createPatchChannel,
Expand Down Expand Up @@ -112,7 +112,7 @@ export function useTasksFormBuilder(options: TasksFormBuilderOptions): TasksForm

const ready = editState.ready && connectionState === 'connected'

const patchChannel = useMemo(() => createPatchChannel(), [])
const [patchChannel] = useState(() => createPatchChannel())
if (formState === null || !ready) {
return {loading: true}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/src/router/RouterProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export interface RouterProviderProps {
* import {useCallback, useMemo} from 'react'
*
* function Root() {
* const router = useMemo(() => route.create('/'), [])
* const [router] = useState(() => route.create('/'))
*
* const [state, setState] = useState<RouterState>({})
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function PaneLayout(
Omit<HTMLProps<HTMLDivElement>, 'as' | 'height' | 'ref' | 'wrap'>,
) {
const {children, minWidth, onCollapse, onExpand, ...restProps} = props
const controller = useMemo(() => createPaneLayoutController(), [])
const [controller] = useState(() => createPaneLayoutController())
const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)
const rootRect = useElementRect(rootElement)
const width = rootRect?.width || 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const PaneLayoutRoot = styled(Flex)`

export default function ResizeStory() {
const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)
const controller = useMemo(() => createPaneLayoutController(), [])
const [controller] = useState(() => createPaneLayoutController())
const collapsed = false
const [state, setState] = useState<PaneLayoutState>({
expandedElement: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const FormView = forwardRef<HTMLDivElement, FormViewProps>(function FormV
// nodes about both remote and local patches.
// - Used by the Portable Text input to modify selections.
// - Used by `withDocument` to reset value.
const patchChannel = useMemo(() => createPatchChannel(), [])
const [patchChannel] = useState(() => createPatchChannel())

const isLocked = editState?.transactionSyncLock?.enabled
const {t} = useTranslation(structureLocaleNamespace)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {observableCallback} from 'observable-callback'
import {useMemo} from 'react'
import {useMemo, useState} from 'react'
import {useObservable} from 'react-rx'
import {concat, fromEvent, merge, of} from 'rxjs'
import {
Expand Down Expand Up @@ -75,8 +75,8 @@ export function useDocumentList(opts: UseDocumentListOpts): UseDocumentListHookV
[searchFilter, paramsProp],
)

const [onRetry$, onRetry] = useMemo(() => observableCallback(), [])
const [onFetchFullList$, onLoadFullList] = useMemo(() => observableCallback(), [])
const [[onRetry$, onRetry]] = useState(() => observableCallback())
const [[onFetchFullList$, onLoadFullList]] = useState(() => observableCallback())

const queryResults$ = useMemo(() => {
const listenSearchQueryArgs = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export interface Panes {
}

function useRouterPanesStream() {
const routerStateSubject = useMemo(() => new ReplaySubject<RouterState>(1), [])
const [routerStateSubject] = useState(() => new ReplaySubject<RouterState>(1))
const routerPanes$ = useMemo(
() =>
routerStateSubject
Expand Down

0 comments on commit 6e3e7ab

Please sign in to comment.