Wat is Axios?

Axios is een populaire library om HTTP requests te maken naar een API. Het is een alternatief voor de ingebouwde fetch() functie, maar met meer features.

Waarom Axios?

  • Simpeler: Minder code nodig dan fetch()
  • Automatisch JSON: Geen .json() nodig
  • Error handling: Betere foutafhandeling
  • Interceptors: Request/response aanpassen
  • Timeout: Ingebouwde timeout support

Installatie

Installeer Axios via npm:

npm install axios

Import

import axios from 'axios';

GET Request - Data Ophalen

Gebruik axios.get() om data op te halen van een API.

Basis Voorbeeld

import { useState } from 'react';
import { View, Pressable, Text, StyleSheet } from 'react-native';
import axios from 'axios';

export default function App() {
  const [data, setData] = useState(null);

  const fetchData = async () => {
    try {
      const response = await axios.get('https://jsonplaceholder.typicode.com/users/1');
      setData(response.data);
      console.log(response.data);
    } catch (error) {
      console.error('Error:', error);
    }
  };

  return (
    <View style={styles.container}>
      <Pressable style={styles.button} onPress={fetchData}>
        <Text style={styles.buttonText}>Haal Data Op</Text>
      </Pressable>

      {data && (
        <View style={styles.dataContainer}>
          <Text style={styles.name}>{data.name}</Text>
          <Text>{data.email}</Text>
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  button: {
    backgroundColor: '#007AFF',
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
  },
  buttonText: {
    color: 'white',
    fontWeight: 'bold',
  },
  dataContainer: {
    marginTop: 20,
    padding: 15,
    backgroundColor: '#f5f5f5',
    borderRadius: 8,
  },
  name: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 5,
  },
});

response.data bevat:

  • response.data - De response body (automatisch parsed als JSON)
  • response.status - Status code (200, 404, etc.)
  • response.headers - Response headers

Lijst Ophalen

import { useState } from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
import axios from 'axios';

export default function UserList() {
  const [users, setUsers] = useState([]);

  const fetchUsers = async () => {
    try {
      const response = await axios.get('https://jsonplaceholder.typicode.com/users');
      setUsers(response.data);
    } catch (error) {
      console.error('Error:', error);
    }
  };

  return (
    <View style={styles.container}>
      <FlatList
        data={users}
        keyExtractor={(item) => item.id.toString()}
        renderItem={({ item }) => (
          <View style={styles.userCard}>
            <Text style={styles.name}>{item.name}</Text>
            <Text>{item.email}</Text>
          </View>
        )}
      />
    </View>
  );
}

POST Request - Data Versturen

Gebruik axios.post() om data naar een API te sturen.

Data Verzenden

import { useState } from 'react';
import { View, TextInput, Pressable, Text, Alert, StyleSheet } from 'react-native';
import axios from 'axios';

export default function CreateUser() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  const createUser = async () => {
    try {
      const response = await axios.post(
        'https://jsonplaceholder.typicode.com/users',
        {
          name: name,
          email: email,
        }
      );
      
      console.log('Created:', response.data);
      Alert.alert('Success', 'User aangemaakt!');
      
      // Reset form
      setName('');
      setEmail('');
    } catch (error) {
      console.error('Error:', error);
      Alert.alert('Fout', 'Er ging iets mis');
    }
  };

  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        placeholder="Naam"
        value={name}
        onChangeText={setName}
      />

      <TextInput
        style={styles.input}
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        keyboardType="email-address"
      />

      <Pressable style={styles.button} onPress={createUser}>
        <Text style={styles.buttonText}>Aanmaken</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ddd',
    padding: 12,
    borderRadius: 8,
    marginBottom: 15,
  },
  button: {
    backgroundColor: '#007AFF',
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
  },
  buttonText: {
    color: 'white',
    fontWeight: 'bold',
  },
});

Andere HTTP Methodes

// PUT - Update
await axios.put('https://api.com/users/1', { name: 'Nieuwe Naam' });

// PATCH - Partial Update
await axios.patch('https://api.com/users/1', { email: 'new@email.com' });

// DELETE - Verwijderen
await axios.delete('https://api.com/users/1');

Loading States & Error Handling

Toon loading indicator en errors aan gebruikers.

Met Loading State

import { useState } from 'react';
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
import axios from 'axios';

export default function App() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const fetchData = async () => {
    setLoading(true);
    setError(null);
    
    try {
      const response = await axios.get('https://jsonplaceholder.typicode.com/users/1');
      setData(response.data);
    } catch (error) {
      setError('Er ging iets mis bij het ophalen van data');
      console.error('Error:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <View style={styles.container}>
      {loading && <ActivityIndicator size="large" color="#007AFF" />}
      
      {error && (
        <View style={styles.errorBox}>
          <Text style={styles.errorText}>{error}</Text>
        </View>
      )}
      
      {data && !loading && (
        <View style={styles.dataContainer}>
          <Text>{data.name}</Text>
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: 'center',
  },
  errorBox: {
    backgroundColor: '#ffebee',
    padding: 15,
    borderRadius: 8,
    borderLeftWidth: 4,
    borderLeftColor: '#f44336',
  },
  errorText: {
    color: '#c62828',
  },
  dataContainer: {
    padding: 15,
    backgroundColor: '#f5f5f5',
    borderRadius: 8,
  },
});

Best practices:

  • Altijd try-catch gebruiken
  • Loading state tonen tijdens request
  • Errors tonen aan gebruiker
  • finally block voor cleanup

Data Ophalen bij Component Mount

Gebruik useEffect om data automatisch op te halen als component laadt.

import { useState, useEffect } from 'react';
import { View, Text, FlatList, ActivityIndicator, StyleSheet } from 'react-native';
import axios from 'axios';

export default function PostList() {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchPosts();
  }, []);

  const fetchPosts = async () => {
    try {
      const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
      setPosts(response.data);
    } catch (error) {
      console.error('Error:', error);
    } finally {
      setLoading(false);
    }
  };

  if (loading) {
    return (
      <View style={styles.centered}>
        <ActivityIndicator size="large" color="#007AFF" />
      </View>
    );
  }

  return (
    <FlatList
      data={posts}
      keyExtractor={(item) => item.id.toString()}
      renderItem={({ item }) => (
        <View style={styles.postCard}>
          <Text style={styles.title}>{item.title}</Text>
          <Text style={styles.body}>{item.body}</Text>
        </View>
      )}
    />
  );
}

const styles = StyleSheet.create({
  centered: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  postCard: {
    backgroundColor: 'white',
    padding: 15,
    marginVertical: 8,
    marginHorizontal: 16,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOpacity: 0.1,
    shadowRadius: 3,
    elevation: 2,
  },
  title: {
    fontSize: 16,
    fontWeight: 'bold',
    marginBottom: 5,
  },
  body: {
    fontSize: 14,
    color: '#666',
  },
});

Volledig Voorbeeld - Todo App met API

import { useState, useEffect } from 'react';
import { View, TextInput, Pressable, Text, FlatList, ActivityIndicator, StyleSheet } from 'react-native';
import axios from 'axios';

const API_URL = 'https://jsonplaceholder.typicode.com/todos';

export default function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [text, setText] = useState('');
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchTodos();
  }, []);

  const fetchTodos = async () => {
    try {
      const response = await axios.get(API_URL + '?_limit=10');
      setTodos(response.data);
    } catch (error) {
      console.error('Error:', error);
    } finally {
      setLoading(false);
    }
  };

  const addTodo = async () => {
    if (!text.trim()) return;

    try {
      const response = await axios.post(API_URL, {
        title: text,
        completed: false,
      });
      
      setTodos([response.data, ...todos]);
      setText('');
    } catch (error) {
      console.error('Error:', error);
    }
  };

  const toggleTodo = async (id) => {
    const todo = todos.find(t => t.id === id);
    
    try {
      await axios.patch(`${API_URL}/${id}`, {
        completed: !todo.completed,
      });
      
      setTodos(
        todos.map(t =>
          t.id === id ? { ...t, completed: !t.completed } : t
        )
      );
    } catch (error) {
      console.error('Error:', error);
    }
  };

  const deleteTodo = async (id) => {
    try {
      await axios.delete(`${API_URL}/${id}`);
      setTodos(todos.filter(t => t.id !== id));
    } catch (error) {
      console.error('Error:', error);
    }
  };

  if (loading) {
    return (
      <View style={styles.centered}>
        <ActivityIndicator size="large" color="#007AFF" />
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Todos</Text>

      <View style={styles.inputContainer}>
        <TextInput
          style={styles.input}
          placeholder="Nieuwe todo..."
          value={text}
          onChangeText={setText}
          onSubmitEditing={addTodo}
        />
        <Pressable style={styles.addButton} onPress={addTodo}>
          <Text style={styles.addButtonText}>+</Text>
        </Pressable>
      </View>

      <FlatList
        data={todos}
        keyExtractor={(item) => item.id.toString()}
        renderItem={({ item }) => (
          <View style={styles.todoItem}>
            <Pressable
              style={styles.todoText}
              onPress={() => toggleTodo(item.id)}
            >
              <Text
                style={[
                  styles.text,
                  item.completed && styles.completedText,
                ]}
              >
                {item.title}
              </Text>
            </Pressable>
            
            <Pressable onPress={() => deleteTodo(item.id)}>
              <Text style={styles.deleteButton}>X</Text>
            </Pressable>
          </View>
        )}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#f5f5f5',
  },
  centered: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 32,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  inputContainer: {
    flexDirection: 'row',
    marginBottom: 20,
  },
  input: {
    flex: 1,
    borderWidth: 1,
    borderColor: '#ddd',
    padding: 12,
    borderRadius: 8,
    backgroundColor: 'white',
    marginRight: 10,
  },
  addButton: {
    backgroundColor: '#007AFF',
    width: 50,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  addButtonText: {
    color: 'white',
    fontSize: 24,
    fontWeight: 'bold',
  },
  todoItem: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: 'white',
    padding: 15,
    borderRadius: 8,
    marginBottom: 10,
  },
  todoText: {
    flex: 1,
  },
  text: {
    fontSize: 16,
  },
  completedText: {
    textDecorationLine: 'line-through',
    color: '#999',
  },
  deleteButton: {
    color: 'red',
    fontSize: 18,
    fontWeight: 'bold',
    padding: 5,
  },
});

Dit voorbeeld toont:

  • GET - Todos ophalen bij mount
  • POST - Nieuwe todo aanmaken
  • PATCH - Todo status updaten
  • DELETE - Todo verwijderen
  • Loading state met ActivityIndicator
  • Error handling met try-catch

Samenvatting

axios.get()

Data ophalen

axios.post()

Data versturen

try-catch

Error handling

useEffect

Data bij mount ophalen

Je hebt nu geleerd:

  • Axios installeren en gebruiken
  • GET requests om data op te halen
  • POST requests om data te versturen
  • Loading states en error handling
  • Data ophalen bij component mount met useEffect
  • Complete CRUD app met API integratie