React Native is built on top of React, so understanding React fundamentals is essential. This guide covers the core React concepts you’ll use every day in React Native development.
Components
Components are the building blocks of React Native apps. A component is a JavaScript function that returns JSX describing what should appear on screen.
Function Components
import { View , Text } from 'react-native' ;
function Welcome () {
return (
< View >
< Text > Hello, World! </ Text >
</ View >
);
}
export default Welcome ;
JSX Syntax
JSX lets you write markup inside JavaScript. In React Native, you use components like <View> and <Text> instead of HTML elements:
// This JSX:
< View style = { { padding: 16 } } >
< Text > Hello </ Text >
</ View >
// Is transformed to:
React . createElement (
View ,
{ style: { padding: 16 }},
React . createElement ( Text , null , 'Hello' )
);
Props
Props (properties) let you pass data from parent to child components. Props are read-only and cannot be modified by the child.
import { View , Text , StyleSheet } from 'react-native' ;
function Greeting ( props ) {
return (
< View style = { styles . container } >
< Text style = { styles . text } > Hello, { props . name } ! </ Text >
< Text > You are { props . age } years old. </ Text >
</ View >
);
}
// Using the component
function App () {
return (
< View >
< Greeting name = "Alice" age = { 25 } />
< Greeting name = "Bob" age = { 30 } />
</ View >
);
}
const styles = StyleSheet . create ({
container: {
padding: 16 ,
backgroundColor: '#f0f0f0' ,
marginBottom: 8 ,
},
text: {
fontSize: 18 ,
fontWeight: 'bold' ,
},
});
Destructuring Props
Common pattern for cleaner code:
// Instead of props.name, props.age
function Greeting ({ name , age }) {
return (
< View >
< Text > Hello, { name } ! </ Text >
< Text > Age: { age } </ Text >
</ View >
);
}
State
State is data that changes over time. When state changes, React re-renders the component.
useState Hook
import { View , Text , Button } from 'react-native' ;
import { useState } from 'react' ;
function Counter () {
const [ count , setCount ] = useState ( 0 );
return (
< View >
< Text > Count: { count } </ Text >
< Button
title = "Increment"
onPress = { () => setCount ( count + 1 ) }
/>
< Button
title = "Decrement"
onPress = { () => setCount ( count - 1 ) }
/>
< Button
title = "Reset"
onPress = { () => setCount ( 0 ) }
/>
</ View >
);
}
Multiple State Variables
import { View , TextInput , Text , Button } from 'react-native' ;
import { useState } from 'react' ;
function LoginForm () {
const [ email , setEmail ] = useState ( '' );
const [ password , setPassword ] = useState ( '' );
const [ isLoading , setIsLoading ] = useState ( false );
const handleLogin = () => {
setIsLoading ( true );
// Perform login...
};
return (
< View >
< TextInput
placeholder = "Email"
value = { email }
onChangeText = { setEmail }
/>
< TextInput
placeholder = "Password"
value = { password }
onChangeText = { setPassword }
secureTextEntry
/>
< Button
title = "Login"
onPress = { handleLogin }
disabled = { isLoading }
/>
</ View >
);
}
State updates are asynchronous. Don’t rely on the previous state value immediately after calling the setter.
Hooks
Hooks let you use state and other React features in function components.
useEffect Hook
Run side effects after rendering:
import { View , Text } from 'react-native' ;
import { useState , useEffect } from 'react' ;
function UserProfile ({ userId }) {
const [ user , setUser ] = useState ( null );
const [ loading , setLoading ] = useState ( true );
useEffect (() => {
// This runs after component mounts and when userId changes
setLoading ( true );
fetch ( `https://api.example.com/users/ ${ userId } ` )
. then ( response => response . json ())
. then ( data => {
setUser ( data );
setLoading ( false );
});
}, [ userId ]); // Dependency array
if ( loading ) {
return < Text > Loading... </ Text > ;
}
return (
< View >
< Text > Name: { user . name } </ Text >
< Text > Email: { user . email } </ Text >
</ View >
);
}
useEffect Cleanup
import { useEffect } from 'react' ;
import { AppState } from 'react-native' ;
function MyComponent () {
useEffect (() => {
const subscription = AppState . addEventListener ( 'change' , ( state ) => {
console . log ( 'App state changed to:' , state );
});
// Cleanup function
return () => {
subscription . remove ();
};
}, []); // Empty array = run once on mount
}
Common Hooks
useState
useEffect
useRef
useCallback
const [ value , setValue ] = useState ( initialValue );
Manage component state useEffect (() => {
// Side effect code
return () => {
// Cleanup
};
}, [ dependencies ]);
Perform side effects const inputRef = useRef ( null );
inputRef . current . focus ();
Reference DOM/native elements const memoizedCallback = useCallback (
() => {
doSomething ( a , b );
},
[ a , b ]
);
Memoize callback functions
Conditional Rendering
Render different content based on conditions:
import { View , Text , Button } from 'react-native' ;
import { useState } from 'react' ;
function LoginScreen () {
const [ isLoggedIn , setIsLoggedIn ] = useState ( false );
return (
< View >
{ isLoggedIn ? (
< View >
< Text > Welcome back! </ Text >
< Button title = "Logout" onPress = { () => setIsLoggedIn ( false ) } />
</ View >
) : (
< View >
< Text > Please log in </ Text >
< Button title = "Login" onPress = { () => setIsLoggedIn ( true ) } />
</ View >
) }
</ View >
);
}
Logical && Operator
function Notification ({ message , show }) {
return (
< View >
{ show && (
< View style = { { backgroundColor: 'yellow' , padding: 10 } } >
< Text > { message } </ Text >
</ View >
) }
</ View >
);
}
Rendering Lists
Use map() to render arrays of data:
import { View , Text } from 'react-native' ;
function TodoList () {
const todos = [
{ id: 1 , text: 'Learn React Native' },
{ id: 2 , text: 'Build an app' },
{ id: 3 , text: 'Deploy to stores' },
];
return (
< View >
{ todos . map ( todo => (
< View key = { todo . id } >
< Text > { todo . text } </ Text >
</ View >
)) }
</ View >
);
}
Always include a unique key prop when rendering lists. Keys help React identify which items have changed.
Component Composition
Build complex UIs by combining smaller components:
import { View , Text , Image , StyleSheet } from 'react-native' ;
function Avatar ({ url , size = 50 }) {
return (
< Image
source = { { uri: url } }
style = { { width: size , height: size , borderRadius: size / 2 } }
/>
);
}
function UserCard ({ name , role , avatarUrl }) {
return (
< View style = { styles . card } >
< Avatar url = { avatarUrl } size = { 60 } />
< View style = { styles . info } >
< Text style = { styles . name } > { name } </ Text >
< Text style = { styles . role } > { role } </ Text >
</ View >
</ View >
);
}
const styles = StyleSheet . create ({
card: {
flexDirection: 'row' ,
padding: 16 ,
backgroundColor: 'white' ,
borderRadius: 8 ,
marginBottom: 8 ,
},
info: {
marginLeft: 12 ,
justifyContent: 'center' ,
},
name: {
fontSize: 16 ,
fontWeight: 'bold' ,
},
role: {
fontSize: 14 ,
color: '#666' ,
},
});
React Native-Specific Considerations
No HTML Elements
// ❌ Wrong - HTML doesn't work in React Native
< div >
< p > Hello </ p >
</ div >
// ✅ Correct - Use React Native components
< View >
< Text > Hello </ Text >
</ View >
StyleSheet API
import { StyleSheet } from 'react-native' ;
const styles = StyleSheet . create ({
container: {
flex: 1 ,
backgroundColor: '#fff' ,
},
});
Event Handlers
// Web: onClick
< button onClick = { () => console . log ( 'clicked' ) } > Click </ button >
// React Native: onPress
< Button onPress = { () => console . log ( 'pressed' ) } title = "Press" />
Next Steps
Handling Text Input Learn to work with forms and user input
Using Lists Render large lists efficiently with FlatList