Render props and slot patterns let parents own behavior while children own markup - so you compose deep navigation trees without stacking wrapper components around every screen. Render props pass state through a function; slot patterns (as in Expo Router layouts) reserve a hole where the active child route renders.
import type { ReactNode } from "react";type RenderProp<T> = (value: T) => ReactNode;interface DataRendererProps<T> { data: T; children: RenderProp<T>;}// Named render prop when children is already used for compositioninterface ListProps<T> { items: T[]; renderRow: RenderProp<{ item: T; index: number }>; keyExtractor: (item: T) => string;}
Prefer explicit names (renderHeader, renderEmpty) when children is also a valid React node.
Generic parents (AsyncList<T>) keep item types flowing to the callback parameter.
Type the render argument as an interface so screens get autocomplete on reload, status, etc.
Inline render functions in lists - children={(ctx) => <Row {...ctx} />} defined inside a parent re-creates the function every render and can defeat memo. Fix: Hoist a stable child component or pass renderRow from useCallback.
Wrapper hell in navigators - Nesting five providers in every _layout.tsx obscures the actual screen. Fix: Push cross-cutting providers to the root layout; use slots for route-level chrome only.
Using render props when a hook suffices - Toggle with only isOn/toggle does not need a function child if every caller renders the same row. Fix: Export useToggle and a dumb row - see Custom Hooks for UI Logic.
Calling hooks inside render props - children={() => { const x = useFoo(); ... }} violates the Rules of Hooks. Fix: Move hook calls into a child component rendered by the function.
Slot without flex - Forgetting flex: 1 on the slot container yields blank or clipped child screens. Fix: Give the slot wrapper flex: 1 in full-screen layouts.
Async render prop reload loops - useEffect(() => reload(), [items]) when reload sets items causes infinite fetch. Fix: Depend on stable keys; load once on mount or on explicit user action.
Untyped children as Function - children: Function loses type safety. Fix:children: (state: ToggleRenderProps) => ReactNode.