Spaces:
Sleeping
Sleeping
Fetch to Axios Migration Guide
This document outlines the pattern for migrating fetch API calls to axios in our codebase.
Why migrate from fetch to axios?
Axios provides several advantages over the native fetch API:
- Automatic JSON data transformation
- Better error handling
- Request/response interceptors
- Simpler syntax for common operations
- Consistent error objects
Migration Pattern
1. Import axios
First, add the axios import to your file:
import axios from 'axios';
2. Replace GET requests
Before (with fetch):
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
// other headers...
},
mode: 'cors',
credentials: 'include' // or 'omit'
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Failed: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data;
After (with axios):
const response = await axios.get(url, {
headers: {
'Content-Type': 'application/json',
// other headers...
},
withCredentials: true // replaces credentials: 'include'
// Note: 'mode: cors' is not needed with axios
});
// No need to check response.ok - axios throws on error status codes
// No need to parse JSON - axios does this automatically
return response.data;
3. Replace POST requests
Before (with fetch):
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// other headers...
},
body: JSON.stringify(data),
mode: 'cors',
credentials: 'include' // or 'omit'
});
if (!response.ok) {
throw new Error(`Failed: ${response.status} ${response.statusText}`);
}
const responseData = await response.json();
return responseData;
After (with axios):
const response = await axios.post(url, data, {
headers: {
'Content-Type': 'application/json',
// other headers...
},
withCredentials: true // if needed
});
return response.data;
4. Replace PUT requests
Before (with fetch):
const response = await fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
// other headers...
},
body: JSON.stringify(data),
mode: 'cors',
credentials: 'include' // or 'omit'
});
if (!response.ok) {
throw new Error(`Failed: ${response.status} ${response.statusText}`);
}
const responseData = await response.json();
return responseData;
After (with axios):
const response = await axios.put(url, data, {
headers: {
'Content-Type': 'application/json',
// other headers...
},
withCredentials: true // if needed
});
return response.data;
5. Replace DELETE requests
Before (with fetch):
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
// other headers...
},
mode: 'cors',
credentials: 'include' // or 'omit'
});
if (!response.ok) {
throw new Error(`Failed: ${response.status} ${response.statusText}`);
}
// Handle response as needed
After (with axios):
const response = await axios.delete(url, {
headers: {
'Content-Type': 'application/json',
// other headers...
},
withCredentials: true // if needed
});
// response.data is already parsed if JSON was returned
6. Error Handling
Before (with fetch):
try {
const response = await fetch(url);
if (!response.ok) {
const errorText = await response.text();
console.error(`API error: ${response.status} ${response.statusText}`, errorText);
throw new Error(`Failed: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Request failed:', error);
throw error;
}
After (with axios):
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
console.error('API error:', error.message);
console.error('Status:', error.response?.status);
console.error('Data:', error.response?.data);
throw new Error(`API Error: ${error.response?.status} ${error.message}`);
}
console.error('Request failed:', error);
throw error;
}
Common Patterns by File Type
Service Files
For service files, follow this general pattern:
import axios from 'axios';
import { API_BASE_URL } from '@/config';
export const exampleService = {
getAll: async () => {
try {
const response = await axios.get(`${API_BASE_URL}/api/resource`, {
headers: {
'Content-Type': 'application/json',
},
withCredentials: false
});
return response.data;
} catch (error) {
console.error('Error:', error);
return []; // or throw error depending on your error handling strategy
}
},
getById: async (id) => {
try {
const response = await axios.get(`${API_BASE_URL}/api/resource/${id}`);
return response.data;
} catch (error) {
console.error(`Error fetching resource ${id}:`, error);
throw error;
}
},
create: async (data) => {
try {
const response = await axios.post(`${API_BASE_URL}/api/resource`, data);
return response.data;
} catch (error) {
console.error('Error creating resource:', error);
throw error;
}
}
// etc.
};
Component Files
For component files, integrate axios calls as follows:
import axios from 'axios';
import { API_BASE_URL } from '@/config';
const YourComponent = () => {
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get(`${API_BASE_URL}/api/resource`);
setData(response.data);
} catch (error) {
console.error('Error fetching data:', error);
setError('Failed to load data');
} finally {
setLoading(false);
}
};
fetchData();
}, []);
// rest of component
};
Remaining Files to Update
Based on our analysis, these files need to be updated:
- src/pages/project-detail.tsx
- src/pages/project-edit.tsx
- src/pages/projects.tsx
- src/components/appraisal/AppraisalForm.tsx
- src/pages/appraisal/assessment-areas.tsx
- src/utils/create-indicators.js
- src/pages/appraisal/competencies.tsx
- src/pages/appraisal/cycles.tsx
- src/pages/appraisal/hr-remarks.tsx
- src/pages/appraisal/management-remarks.tsx
- src/pages/appraisal/manager-dashboard.tsx
Follow the patterns in this guide to update these files.