Sending a POST Request in React Native
Sending a POST Request
~9 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
While GET retrieves data, POST sends data TO a server – the classic case for forms: registration, contact forms, creating a new record. This time using the built-in fetch() API instead of Axios, for a direct comparison of the two approaches.
1. Description
With fetch(), method, headers, and body must be specified EXPLICITLY – unlike Axios' axios.post(url, data), fetch() handles neither the Content-Type header nor the JSON serialization of the body automatically.
2. Short example
const response = await fetch('https://api.example.com/contacts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Anna' }),
});
const data = await response.json();3. Complete project: a feedback form
npx create-expo-app post-request-demo
cd post-request-demoimport { useState } from 'react';
import { View, TextInput, Button, Text, ActivityIndicator, StyleSheet } from 'react-native';
export default function App() {
const [name, setName] = useState('');
const [message, setMessage] = useState('');
const [submitting, setSubmitting] = useState(false);
const [result, setResult] = useState(null);
async function submit() {
setSubmitting(true);
setResult(null);
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: name, body: message }),
});
if (!response.ok) {
throw new Error(`Server responded with status ${response.status}`);
}
const data = await response.json();
setResult(`Sent! New ID: ${data.id}`);
setName('');
setMessage('');
} catch (error) {
setResult(`Error: ${error.message}`);
} finally {
setSubmitting(false);
}
}
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Your name"
value={name}
onChangeText={setName}
/>
<TextInput
style={[styles.input, styles.multiline]}
placeholder="Your message"
value={message}
onChangeText={setMessage}
multiline
/>
<Button
title="Submit"
onPress={submit}
disabled={submitting || !name || !message}
/>
{submitting && <ActivityIndicator style={styles.spinner} />}
{result && <Text style={styles.result}>{result}</Text>}
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, paddingTop: 60, paddingHorizontal: 24 },
input: { borderWidth: 1, borderColor: '#d1d5db', borderRadius: 8, padding: 10, marginBottom: 12 },
multiline: { height: 100, textAlignVertical: 'top' },
spinner: { marginTop: 16 },
result: { marginTop: 16, textAlign: 'center' },
});4. Explanation
headers: {{ 'Content-Type': 'application/json' }}is MANDATORY withfetch()so the server correctly interprets the body as JSON – without this header, it's often treated as plain text.body: JSON.stringify(...)–fetch()does NOT serialize automatically, unlike Axios; the object must be manually converted into a JSON string.response.okchecks whether the status code is in the 200–299 range –fetch()does NOT throw an error automatically on a 4xx/5xx status (unlike Axios); you must check this yourself.disabled={{submitting || !name || !message}}prevents both duplicate submissions during an in-flight request AND empty form submissions in a single expression.