generate-api-slice-thunk
v1.0.5
Published
A utility to generate Redux Toolkit slices and async thunks for API requests.
Maintainers
Readme
generate-api-slice-thunk
A utility library that generates Redux Toolkit slices and async thunks for API requests in React Native apps with minimal boilerplate.
Features
- Automatically generates Redux Toolkit slices for your API requests
- Creates async thunks with proper loading, success, and error states
- Provides built-in actions to reset or update state directly
- Supports token-based authentication
- Handles multipart form data requests
- Optimized for React Native applications
- Customizable API request handling
Installation
npm install generate-api-slice-thunkor
yarn add generate-api-slice-thunkQuick Start
Here's a simple example of how to use generate-api-slice-thunk in a React Native project:
import generateApiSliceAndThunk from "generate-api-slice-thunk";
// Create a slice and thunk for login API
const { slice: loginSlice, request: loginThunk } = generateApiSliceAndThunk(
"loginSlice",
{
endPoint: "/login",
method: "post",
tokenRequired: false,
isMultiPart: false,
},
async (params, options) => {
const { endPoint, method, tokenRequired, isMultiPart } = options;
const baseUrl = "https://api.example.com";
const response = await fetch(baseUrl + endPoint, {
method,
headers: {
"Content-Type": isMultiPart
? "multipart/form-data"
: "application/json",
...(tokenRequired && { Authorization: `Bearer ${yourTokenHere}` }),
},
body: isMultiPart ? params : JSON.stringify(params),
});
return response.json();
}
);
// Export the slice and thunk for use in your app
export { loginSlice, loginThunk };Setup Guide
Step 1: Project Structure
Create an organized structure for your API services in your React Native project:
src/
└── Networking/
└── User/
└── userServices.jsStep 2: Create Service File
In your userServices.js file:
import generateApiSliceAndThunk from "generate-api-slice-thunk";
// Login API
const { slice: loginSlice, request: loginThunk } = generateApiSliceAndThunk(
"loginSlice",
{
endPoint: "/login",
method: "post",
tokenRequired: false,
isMultiPart: false,
},
async (params, options) => {
const { endPoint, method, tokenRequired, isMultiPart } = options;
const baseUrl = "https://api.example.com";
const response = await fetch(baseUrl + endPoint, {
method,
headers: {
"Content-Type": isMultiPart
? "multipart/form-data"
: "application/json",
...(tokenRequired && { Authorization: `Bearer ${yourTokenHere}` }),
},
body: isMultiPart ? params : JSON.stringify(params),
});
return response.json();
}
);
export { loginSlice, loginThunk };Step 3: Configure Redux Store
import { configureStore, combineReducers } from "@reduxjs/toolkit";
import { persistStore, persistReducer } from "redux-persist";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { loginSlice } from "./Networking/User/userServices";
const persistConfig = {
key: "root",
storage: AsyncStorage,
whitelist: ["loginSlice"], // Only persist login data
};
const rootReducer = combineReducers({
loginSlice: loginSlice.reducer,
// Add other reducers here
});
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
});
export const persistor = persistStore(store);Step 4: Using the API in Components
import React, { useState } from "react";
import { View, Text, TextInput, Button } from "react-native";
import { useDispatch, useSelector } from "react-redux";
import { loginThunk, loginSlice } from "../Networking/User/userServices";
const LoginScreen = () => {
const dispatch = useDispatch();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
// Get data from store
const userData = useSelector((state) => state.loginSlice.data);
const handleLogin = async () => {
try {
const response = await dispatch(
loginThunk({
username,
password,
})
).unwrap();
console.log("Login successful:", response);
// Navigate or perform actions on success
} catch (error) {
console.error("Login failed:", error);
// Handle error
}
};
const handleLogout = () => {
// Reset the state to null
dispatch(loginSlice.actions.reset());
};
return (
<View style={{ padding: 20 }}>
{userData ? (
<>
<Text>Welcome, {userData.name}!</Text>
<Button title="Logout" onPress={handleLogout} />
</>
) : (
<>
<TextInput
value={username}
onChangeText={setUsername}
placeholder="Username"
style={{ borderWidth: 1, padding: 10, marginBottom: 10 }}
/>
<TextInput
value={password}
onChangeText={setPassword}
placeholder="Password"
secureTextEntry
style={{ borderWidth: 1, padding: 10, marginBottom: 20 }}
/>
<Button title="Login" onPress={handleLogin} />
</>
)}
</View>
);
};
export default LoginScreen;API Reference
generateApiSliceAndThunk(sliceName, options, apiCallback)
Creates a Redux Toolkit slice and async thunk for an API endpoint.
Parameters:
sliceName(string): Name of the sliceoptions(object): Configuration for APIendPoint(string): API endpoint (e.g., '/login')method(string): HTTP method ('get', 'post', 'put', 'delete')tokenRequired(boolean): Whether authentication token is requiredisMultiPart(boolean): Whether to use multipart/form-data
apiCallback(function): Custom function to handle API requests
Returns:
slice: Redux Toolkit slice with reducer and actionsslice.actions.reset(): Action to reset state data to nullslice.actions.update(newData): Action to directly update state data
request: Async thunk function for API requests
State Structure
Each generated slice will have the following state structure:
{
data: null; // API response data or manually updated data
}Built-in Actions
The generated slice includes these built-in actions:
reset
Resets the state data to null. Useful for logout or clearing data.
dispatch(yourSlice.actions.reset());update
Directly updates the state data with new values. Useful for local updates without API calls.
dispatch(yourSlice.actions.update(newData));Examples
Image Upload with Multipart Form Data
const { slice: uploadSlice, request: uploadThunk } = generateApiSliceAndThunk(
"uploadSlice",
{
endPoint: "/upload",
method: "post",
tokenRequired: true,
isMultiPart: true,
},
async (formData, options) => {
const { endPoint } = options;
const baseUrl = "https://api.example.com";
// For React Native, you'll need to properly format your FormData
const formDataObj = new FormData();
formDataObj.append("image", {
uri: formData.uri,
type: formData.type,
name: formData.fileName,
});
const response = await fetch(baseUrl + endPoint, {
method: "POST",
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${yourTokenHere}`,
},
body: formDataObj,
});
return response.json();
}
);
// In your component:
const handleImageUpload = async (imageUri) => {
const imageData = {
uri: imageUri,
type: "image/jpeg",
fileName: "photo.jpg",
};
dispatch(uploadThunk(imageData));
};Handling User Profile
// Get user profile
dispatch(getUserThunk()).then((response) => {
console.log("User profile:", response.payload);
});
// Update user profile locally before API sync
dispatch(
userSlice.actions.update({
...currentUserData,
name: "New Name",
avatar: "new-avatar-url.jpg",
})
);Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contact
For questions or support, please contact: [email protected]
