Skip to content

Commit

Permalink
fix(ArtistsCollectionPropmt): fix scrolling (#10881)
Browse files Browse the repository at this point in the history
fix: adjust suspense and fix scrolling
  • Loading branch information
araujobarret authored and carlos-motiro committed Oct 2, 2024
1 parent aadbfe2 commit 2d87b0d
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
act,
fireEvent,
screen,
waitFor,
Expand Down Expand Up @@ -168,9 +167,7 @@ describe("inquiry modal", () => {

it("displays the collection prompt", async () => {
initialState = { ...initialState, collectionPromptVisible: true }
const { mockResolveLastOperation } = renderWithRelay({ Artwork: () => mockArtwork })

act(() => mockResolveLastOperation({}))
renderWithRelay({ Artwork: () => mockArtwork })

expect(
screen.getByText("Inquiry sent! Tell us about the artists in your collection.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { MyCollectionArtistsAutosuggestListHeader } from "app/Scenes/MyCollectio
import { FOOTER_HEIGHT } from "app/Scenes/MyCollection/Components/MyCollectionArtistsPrompt/MyCollectionArtistsPromptFooter"
import { extractNodes } from "app/utils/extractNodes"
import { useDebouncedValue } from "app/utils/hooks/useDebouncedValue"
import { useClientQuery } from "app/utils/useClientQuery"
import { FC, useState } from "react"
import { FlatList, Keyboard, KeyboardAvoidingView } from "react-native"
import { graphql, useLazyLoadQuery } from "react-relay"
import { graphql } from "react-relay"

export const MyCollectionArtistsAutosuggest: FC = () => {
const space = useSpace()
Expand All @@ -21,8 +22,10 @@ export const MyCollectionArtistsAutosuggest: FC = () => {

const { debouncedValue: debouncedQuery } = useDebouncedValue({ value: query, delay: 250 })

const data = useLazyLoadQuery<MyCollectionArtistsAutosuggestQuery>(QUERY, {
query: debouncedQuery,
const { data, loading } = useClientQuery<MyCollectionArtistsAutosuggestQuery>({
query: QUERY,
variables: { query: debouncedQuery },
skip: !debouncedQuery,
})

const matches = extractNodes(data?.matchConnection)
Expand Down Expand Up @@ -71,7 +74,7 @@ export const MyCollectionArtistsAutosuggest: FC = () => {
query={query}
debouncedQuery={debouncedQuery}
resultsLength={matches.length}
isLoading={!data}
isLoading={loading}
/>
)}
ListFooterComponent={() => <Flex height={FOOTER_HEIGHT + bottom} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ export const MyCollectionArtistsAutosuggestListHeader: FC<
}

if (isLoading) {
return <LoadingSpinner />
return (
<Flex p={4}>
<LoadingSpinner />
</Flex>
)
}

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Flex, Spinner, Text, useSpace } from "@artsy/palette-mobile"
import { Flex, Text, useSpace } from "@artsy/palette-mobile"
import { useBottomSheet } from "@gorhom/bottom-sheet"
import { MyCollectionArtistsPromptBody } from "app/Scenes/MyCollection/Components/MyCollectionArtistsPrompt/MyCollectionArtistsPromptBody"
import { SNAP_POINTS } from "app/Scenes/MyCollection/Components/MyCollectionBottomSheetModals/MyCollectionBottomSheetModalArtistsPrompt"
import { MyCollectionAddCollectedArtistsStore } from "app/Scenes/MyCollection/Screens/MyCollectionAddCollectedArtists/MyCollectionAddCollectedArtistsStore"
import { MotiView } from "moti"
import { FC, Suspense } from "react"
import { FC } from "react"
import { useDerivedValue } from "react-native-reanimated"

export interface MyCollectionArtistsPromptProps {
Expand All @@ -30,23 +30,15 @@ export const MyCollectionArtistsPrompt: FC<MyCollectionArtistsPromptProps> = ({
}}
>
<Flex px={2} pt={1} pb={2} flex={1}>
<Suspense
fallback={
<Flex justifyContent="center" alignItems="center" flex={1}>
<Spinner />
</Flex>
}
>
<Text variant="md">{title}</Text>
<Text variant="md">{title}</Text>

{!!subtitle && <Text>{subtitle}</Text>}
{!!subtitle && <Text>{subtitle}</Text>}

<Flex pt={2} gap={space(2)} flex={1}>
<MyCollectionAddCollectedArtistsStore.Provider>
<MyCollectionArtistsPromptBody />
</MyCollectionAddCollectedArtistsStore.Provider>
</Flex>
</Suspense>
<Flex pt={2} gap={space(2)} flex={1}>
<MyCollectionAddCollectedArtistsStore.Provider>
<MyCollectionArtistsPromptBody />
</MyCollectionAddCollectedArtistsStore.Provider>
</Flex>
</Flex>
</MotiView>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fireEvent, screen } from "@testing-library/react-native"
import { fireEvent, screen, waitFor } from "@testing-library/react-native"
import { MyCollectionArtistsAutosuggest } from "app/Scenes/MyCollection/Components/MyCollectionArtistsPrompt/MyCollectionArtistsAutosuggest"
import { setupTestWrapper } from "app/utils/tests/setupTestWrapper"
import { Suspense } from "react"
Expand Down Expand Up @@ -49,9 +49,7 @@ describe("MyCollectionArtistsAutosuggest", () => {
afterEach(jest.clearAllMocks)

it("renders", async () => {
const { mockResolveLastOperation } = renderWithRelay()

mockResolveLastOperation({ MatchConnection: () => ({ edges: [] }) })
renderWithRelay()

const input = await screen.findByPlaceholderText("Search for artists on Artsy")
expect(input).toBeOnTheScreen()
Expand All @@ -60,17 +58,20 @@ describe("MyCollectionArtistsAutosuggest", () => {
})

it("renders matches", async () => {
const { mockResolveLastOperation } = renderWithRelay()
const { mockResolveLastOperation, env } = renderWithRelay()

const input = await screen.findByPlaceholderText("Search for artists on Artsy")
fireEvent.changeText(input, "test")

await waitFor(() => expect(env.mock.getAllOperations().length).toBe(1))

mockResolveLastOperation({ MatchConnection: () => ({ edges: matches }) })

expect(await screen.findAllByText(/mock-value-for-field-"name"/)).toHaveLength(2)
})

it("calls expand on focus", async () => {
const { mockResolveLastOperation } = renderWithRelay()

mockResolveLastOperation({ MatchConnection: () => ({ edges: [] }) })
renderWithRelay()

const input = await screen.findByPlaceholderText("Search for artists on Artsy")
fireEvent(input, "focus")
Expand All @@ -79,9 +80,7 @@ describe("MyCollectionArtistsAutosuggest", () => {
})

it("calls collapse on blur", async () => {
const { mockResolveLastOperation } = renderWithRelay()

mockResolveLastOperation({ MatchConnection: () => ({ edges: [] }) })
renderWithRelay()

const input = await screen.findByPlaceholderText("Search for artists on Artsy")
fireEvent(input, "focus")
Expand All @@ -91,11 +90,17 @@ describe("MyCollectionArtistsAutosuggest", () => {
})

it("does not call collapse on blur given matches", async () => {
const { mockResolveLastOperation } = renderWithRelay()
const { env, mockResolveLastOperation } = renderWithRelay()

const input = await screen.findByPlaceholderText("Search for artists on Artsy")
fireEvent.changeText(input, "test")

await waitFor(() => expect(env.mock.getAllOperations().length).toBe(1))

mockResolveLastOperation({ MatchConnection: () => ({ edges: matches }) })

const input = await screen.findByPlaceholderText("Search for artists on Artsy")
await screen.findAllByText(/mock-value-for-field-"name"/)

fireEvent(input, "focus")
fireEvent(input, "blur")

Expand All @@ -104,9 +109,7 @@ describe("MyCollectionArtistsAutosuggest", () => {

it("calls collapse on clear", async () => {
jest.spyOn(Keyboard, "isVisible").mockReturnValue(false)
const { mockResolveLastOperation } = renderWithRelay()

mockResolveLastOperation({ MatchConnection: () => ({ edges: [] }) })
renderWithRelay()

const input = await screen.findByPlaceholderText("Search for artists on Artsy")
fireEvent.changeText(input, "test")
Expand All @@ -119,9 +122,7 @@ describe("MyCollectionArtistsAutosuggest", () => {

it("calls collapse on clear given the keyboard visible", async () => {
jest.spyOn(Keyboard, "isVisible").mockReturnValue(true)
const { mockResolveLastOperation } = renderWithRelay()

mockResolveLastOperation({ MatchConnection: () => ({ edges: [] }) })
renderWithRelay()

const input = await screen.findByPlaceholderText("Search for artists on Artsy")
fireEvent.changeText(input, "test")
Expand Down
18 changes: 17 additions & 1 deletion src/app/utils/useClientQuery.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect, useState } from "react"
import { useUpdateEffect } from "app/utils/useUpdateEffect"
import { useEffect, useRef, useState } from "react"
import { Environment, fetchQuery, GraphQLTaggedNode, useRelayEnvironment } from "react-relay"
import { CacheConfig, FetchQueryFetchPolicy, OperationType } from "relay-runtime"

Expand Down Expand Up @@ -33,7 +34,22 @@ export const useClientQuery = <T extends OperationType>({
const [error, setError] = useState<Error | null>(null)
const [loading, setLoading] = useState(true)

const key = useRef(JSON.stringify(variables))
const prevKey = useRef(key.current)

useUpdateEffect(() => {
key.current = JSON.stringify(variables)
}, [variables])

useEffect(() => {
if (key.current !== prevKey.current) {
setData(null)
setError(null)
setLoading(true)

prevKey.current = key.current
}

if (skip || data || error) return

const exec = async () => {
Expand Down
16 changes: 16 additions & 0 deletions src/app/utils/useUpdateEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useEffect, useRef } from "react"

/**
* Equivalent to `useEffect` but skips initial mount
*/
export const useUpdateEffect: typeof useEffect = (effect, deps) => {
const didMountRef = useRef(false)

useEffect(() => {
if (didMountRef.current) {
return effect()
}

didMountRef.current = true
}, deps)
}

0 comments on commit 2d87b0d

Please sign in to comment.