Summary
The issue is that the “More” tab in an Expo SDK 55 app should not navigate to a screen; instead it must open a quick‑action overlay similar to Evan Bacon’s Twitter demo. The developer has implemented a standard navigation tab but the overlay never appears.
- Key takeaway: A tab cannot both act as a primary navigation destination and open an auxiliary UI.
- Goal: Trigger an overlay from a tab selected event without route changes.
Root Cause
- Standard tab behavior – The
NativeTabs.Triggercomponent interprets every tab tap as a navigation request. - Missing event hook – No
onPresshandler orselectableprop is supplied to intercept the tap. - No overlay state – The component hierarchy lacks a shared state or portal that can display the quick‑action panel.
Why This Happens in Real Systems
- Declarative frameworks (React, React Native) favour routing logic over imperative UI changes.
- Developers often add new navigation contexts to existing navigation stacks, assuming that a non‑screen tab is just a visual placeholder.
- In many apps, the “More” button is wired to a separate hierarchy (e.g., a side drawer), leading to misconceptions that it can be left “empty”.
Real-World Impact
- UX frustration: Users tap “More” expecting options, but nothing changes.
- Reduced discoverability: Hidden actions remain unseen until the developer resists this design pattern.
- Productivity loss: Junior engineers waste time chasing the mistaken assumption that the tab will activate automatically.
Example or Code (if necessary and relevant)
None needed – providing the required pattern suffices.
How Senior Engineers Fix It
- Add an
onPresshandler to the “More” tab to open the overlay. - Use a shared context or state (e.g.,
useStateat a top‑level component) to toggle the overlay’s visibility. - Implement a
Portalor modal that renders the quick‑action items; hide it when the tab is not active. - Prevent navigation by setting the tab’s target to
nullor a no‑op route.
Example pattern (pseudo‑code):
const [showOverlay, setShowOverlay] = useState(false);
const handleMorePress = () => setShowOverlay(true);
…
{showOverlay && (
setShowOverlay(false)} />
)}
- Why it works:
- The
onPressstops the default navigation. - The overlay renders independently of the tab navigator.
Portalensures the overlay appears above all other UI.
- The
Why Juniors Miss It
- Assumption that tabs always navigate – Junior engineers seldom consider that a tab can act purely as a trigger.
- Inadequate testing – Without simulating a press event in isolation, the lack of navigation appears functional.
- Focus on routing – Emphasis on stack navigation makes them overlook the need for a separate stateful component for overlays.