Skip to content

[Feature]: 명시적인 history.exit() 메소드 #134

Open
@CodePsy-2001

Description

@CodePsy-2001

Package Scope

@use-funnel/react-navigation-native

Description

현재로써는 네이티브 앱에서 퍼널을 빠져나오려면 router.navigate('/want-to-go') (expo-router) 등을 이용해야 합니다.
그러나 /want-to-go 가 현재 navigation state의 routes 배열에 없을 경우, navigate() 동작은 push() 와 똑같이 동작하고, 이로 인해 사용자가 네이티브 뒤로가기 등을 입력하면 퍼널로 재진입하는 문제가 있습니다.

다음 코드를 사용하면 대처가 가능하나, 라이브러리 내부에서 navigation state나 각종 key값 등을 다루는 잡다한 로직을 외부로 노출시켜야 하는 문제가 있습니다.

// @/lib/use-funnel.ts
import { useNavigation } from 'expo-router'
import { NavigationProp } from '@react-navigation/native'
import { useCallback } from 'react'

const UseFunnelKey = '__useFunnelState' as const

export function useFunnelExit<FunnelId extends string>(funnelId: FunnelId) {
  const navigation = useNavigation<
    NavigationProp<{
      params?: {
        [key in typeof UseFunnelKey]?: Record<FunnelId, any>
      }
    }>
  >()

  return useCallback(() => {
    const state = navigation.getState()
    const filteredRoutes = state.routes.filter(
      (route) => !route?.params?.[UseFunnelKey]?.[funnelId]
    )
    navigation.reset({
      ...state,
      routes: [...filteredRoutes],
      index: filteredRoutes.length - 1,
    })
  }, [funnelId, navigation])
}

// @/app/tests/funnel.tsx
export default function FunnelTestScreen() {
  const funnel = useFunnel({
    id: FunnelTestScreen.name,
    // ...
  })

  const exit = useFunnelExit(FunnelTestScreen.name)

  return (
    <funnel.Render
      // ...
      lastStep={({ context }) => (
        <ZResultStep
          context={context}
          onConfirm={() => {
            router.navigate('/tests/dummy')
            exit()
          }}
        />
      )}
    />
  )
}

Possible Solution

만약 history.push(), history.replace() 처럼 명시적인 history.exit() API가 있다면 개발자들은 퍼널을 빠져나온 뒤 사용자가 네이티브 뒤로가기 등을 입력할 걱정을 덜 수 있습니다.

// ...
Z_결과={({ context, history }) => (
  <ZResultStep
    context={context}
    onConfirm={() => {
      router.navigate('/tests/dummy')
      history.exit()
    }}
  />
)}
// ...

etc.

  • 먼저 네비게이션한 후 exit() 동작을 해야 안정적입니다.
  • history.clear() 가 좀 더 알맞는 이름일 수도 있습니다.
  • 퍼널 안에 중첩된 퍼널에서는 exit() 동작이 오히려 필요가 없고, 반드시 최외곽 퍼널을 빠져나갈 때만 명시적으로 호출해야 합니다. (저희 팀 프로젝트에서는 exit() 함수 내부적으로 최외곽인지 아닌지를 알아서 판단하게 했습니다.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions