Talk to APIs the same way you do on the web — fetch — but handle the mobile realities: loading and error states, flaky connectivity, and live updates over WebSockets.
Why: fetch is built in and works exactly as on the web. On mobile, always model the three states — loading, error, data — because networks are slow and unreliable. useEffect runs the request once; state drives what the screen shows.
function Users() {
const [users, setUsers] = useState([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then((r) => r.json())
.then(setUsers)
.catch(setError)
.finally(() => setLoading(false))
}, [])
if (loading) return <ActivityIndicator />
if (error) return <Text>Something went wrong</Text>
return <FlatList data={users} renderItem={({ item }) => <Text>{item.name}</Text>} keyExtractor={(u) => String(u.id)} />
}Why: sending data is the same fetch with a method, headers, and a JSON body. On mobile you typically attach an auth token to every request — a small wrapper keeps that consistent. (Storing the token securely is the next lesson.)
async function createPost(token: string, title: string) {
const res = await fetch('https://api.example.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + token,
},
body: JSON.stringify({ title }),
})
if (!res.ok) throw new Error('Request failed: ' + res.status)
return res.json()
}Why: phones go offline constantly — in tunnels, elevators, on bad wifi. The community NetInfo library reports connection status so you can show an offline banner or defer requests. Install it, then subscribe to changes.
// npx expo install @react-native-community/netinfo
import NetInfo from '@react-native-community/netinfo'
useEffect(() => {
const unsubscribe = NetInfo.addEventListener((state) => {
console.log('Connected?', state.isConnected)
})
return unsubscribe
}, [])Why: for chat, live scores, or presence you want a push connection, not polling. The WebSocket API is built in — open a connection, listen for messages, and clean it up on unmount so you do not leak connections.
useEffect(() => {
const ws = new WebSocket('wss://example.com/socket')
ws.onmessage = (event) => {
console.log('message:', event.data)
}
return () => ws.close() // clean up on unmount
}, [])