Files
streamyfin/docs/nested-modals.md
2025-11-11 09:07:34 +01:00

2.2 KiB

Nested Modals with PlatformDropdown

Issue

PlatformDropdowns inside BottomSheetModals don't open on Android, or dropdowns reopen unexpectedly after navigation.

Solution

  1. Add controlled state for each PlatformDropdown:

    const [open, setOpen] = useState(false);
    
    <PlatformDropdown
      open={open}
      onOpenChange={setOpen}
      // ...
    />
    
  2. Memoize groups and callbacks to prevent unnecessary re-renders:

    const handleOption1 = useCallback(() => {
      // handler logic
    }, [dependencies]);
    
    const dropdownGroups = useMemo(() => [
      {
        title: "Group 1",
        options: [
          {
            type: "radio",
            label: "Option 1",
            value: "option1",
            selected: state === "option1",
            onPress: handleOption1,
          },
        ],
      },
    ], [state, handleOption1]);
    
    <PlatformDropdown
      groups={dropdownGroups}
      // ...
    />
    
  3. Use View for triggers, not TouchableOpacity:

    // ✅ Correct
    <PlatformDropdown
      trigger={<View>...</View>}
    />
    
    // ❌ Wrong - causes nested TouchableOpacity conflicts
    <PlatformDropdown
      trigger={<TouchableOpacity>...</TouchableOpacity>}
    />
    
  4. Add stackBehavior='push' to parent BottomSheetModal:

    <BottomSheetModal
      stackBehavior='push'
      // ...
    />
    
  5. Reset dropdown states on modal dismiss:

    const handleDismiss = useCallback(() => {
      setDropdown1Open(false);
      setDropdown2Open(false);
      // reset all dropdown states
      onDismiss?.();
    }, [onDismiss]);
    
    <BottomSheetModal
      onDismiss={handleDismiss}
      // ...
    />
    

Why

  • PlatformDropdown wraps triggers in TouchableOpacity on Android. Nested TouchableOpacity causes touch event conflicts.
  • PlatformDropdown tracks internal isModalShowing state to prevent duplicate showModal() calls when dependencies change.
  • Memoizing groups prevents the useEffect from re-triggering unnecessarily, which can cause modals to reopen after navigation.
  • Dropdown states must be reset on modal dismiss to prevent them from reopening automatically when parent modal reopens.