Don't Define Components Inside Components
Don’t Define Components Inside Components
Section titled “Don’t Define Components Inside Components”Impact: CRITICAL (prevents remount on every render)
Defining a component inside another component creates a new component type on every render. React sees a different component each time and fully remounts it, destroying all state and native views.
A common reason developers do this is to access parent variables without passing props. Always pass props instead.
Incorrect (remounts on every render):
function UserProfile({ user, theme }) { const Avatar = () => ( <Image source={{ uri: user.avatarUrl }} style={theme === 'dark' ? styles.avatarDark : styles.avatarLight} /> )
const Stats = () => ( <View> <Text>{user.followers} followers</Text> <Text>{user.posts} posts</Text> </View> )
return ( <View> <Avatar /> <Stats /> </View> )}Every time UserProfile renders, Avatar and Stats are new component types. React unmounts the old instances and mounts new ones — destroying native views, losing internal state, and re-running all effects.
Correct (define outside, pass props):
function Avatar({ src, theme }: { src: string; theme: string }) { return <Image source={{ uri: src }} style={theme === 'dark' ? styles.avatarDark : styles.avatarLight} />}
function Stats({ followers, posts }: { followers: number; posts: number }) { return ( <View> <Text>{followers} followers</Text> <Text>{posts} posts</Text> </View> )}
function UserProfile({ user, theme }) { return ( <View> <Avatar src={user.avatarUrl} theme={theme} /> <Stats followers={user.followers} posts={user.posts} /> </View> )}Symptoms of this bug in React Native:
- TextInput loses focus on every keystroke
- Reanimated animations restart unexpectedly
- FlatList scroll position resets
useEffectcleanup/setup runs on every parent render- Native view flicker during re-renders
Source: vercel-labs/agent-skills (MIT License)