selam-redux-bodysmart-state
v1.0.0
Published
A powerful package that allows you to easily create Redux slices with pre-built CRUD operations using Redux Toolkit
Maintainers
Readme
Redux Slice Builder
A powerful package that allows you to easily create Redux slices with pre-built CRUD operations using Redux Toolkit.
Features
- 🚀 Easy slice creation with CRUD operations
- 🔧 Pre-built request services
- 📦 TypeScript support
- 🎯 Flexible configuration
- 🔄 Automatic state management
- 📊 Pagination support
Installation
npm install redux-slice-builderQuick Start
1. Configure the Request Service
First, you need to configure the request service with your API client and toast service:
import { configureRequestService } from 'redux-slice-builder';
// Configure the service
configureRequestService({
apiClient: {
get: (url, config) => fetch(url, { method: 'GET', ...config }).then(res => res.json()),
post: (url, data) => fetch(url, { method: 'POST', body: JSON.stringify(data) }).then(res => res.json()),
put: (url, data) => fetch(url, { method: 'PUT', body: JSON.stringify(data) }).then(res => res.json()),
delete: (url) => fetch(url, { method: 'DELETE' }).then(res => res.json()),
},
toastService: {
success: (message) => console.log('Success:', message),
error: (message) => console.error('Error:', message),
},
successMessages: {
created: 'Created successfully!',
updated: 'Updated successfully!',
deleted: 'Deleted successfully!',
}
});2. Create Your Types
// types/User.ts
export interface User {
id: number;
name: string;
email: string;
created_at: string;
updated_at: string;
}
export interface UserFormValues {
id?: number;
name: string;
email: string;
}3. Create Your Controller
// controllers/UserController.ts
import { createControllers } from 'redux-slice-builder';
const storeName = 'users';
export const {
getUsersData,
getUsersDataWithOutPagination,
getUsersAsPagination,
createOrUpdateUser,
deleteUser,
deactivateUser
} = createControllers({
storeName,
endpoints: {
get: '/api/users',
getAll: '/api/users/active',
getAsPagination: '/api/users',
createOrUpdate: '/api/users',
delete: '/api/users',
put: '/api/users/deactivate'
}
});4. Create Your Slice
// slices/UserSlice.ts
import { createSliceWithCRUD, addControllerToSlice, createInitialState } from 'redux-slice-builder';
import { User, UserFormValues } from '../types/User';
import {
getUsersData,
getUsersDataWithOutPagination,
getUsersAsPagination,
createOrUpdateUser,
deleteUser,
deactivateUser
} from '../controllers/UserController';
const initialState = createInitialState<User[]>();
export const usersSlice = createSliceWithCRUD({
name: 'users',
initialState,
customReducers: {
// Add your custom reducers here
updateUserName: (state, action) => {
const { id, name } = action.payload;
const user = state.allData.find((u: User) => u.id === id);
if (user) {
user.name = name;
user.updated_at = new Date().toISOString();
}
}
}
});
// Add controllers to the slice
addControllerToSlice(usersSlice, {
get: getUsersData,
getAll: getUsersDataWithOutPagination,
getAsPagination: getUsersAsPagination,
createOrUpdate: createOrUpdateUser,
delete: deleteUser,
put: deactivateUser
});
export const { updateUserName } = usersSlice.actions;
export default usersSlice.reducer;5. Add to Your Store
// store.ts
import { configureStore } from '@reduxjs/toolkit';
import usersReducer from './slices/UserSlice';
export const store = configureStore({
reducer: {
users: usersReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;6. Use in Your Components
// components/UsersList.tsx
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { RootState, AppDispatch } from '../store';
import {
getUsersData,
getUsersAsPagination,
createOrUpdateUser,
deleteUser
} from '../controllers/UserController';
const UsersList: React.FC = () => {
const dispatch = useDispatch<AppDispatch>();
const { data, allData, loading, getLoading } = useSelector((state: RootState) => state.users);
useEffect(() => {
// Get paginated data
dispatch(getUsersAsPagination({ pageNumber: 1, perPage: 10 }));
// Or get all data
dispatch(getUsersData());
}, [dispatch]);
const handleCreateUser = () => {
dispatch(createOrUpdateUser({
name: 'New User',
email: '[email protected]'
}));
};
const handleDeleteUser = (id: number) => {
dispatch(deleteUser(id));
};
if (getLoading) return <div>Loading...</div>;
return (
<div>
<button onClick={handleCreateUser}>Create User</button>
{data.data.map((user: User) => (
<div key={user.id}>
<span>{user.name}</span>
<button onClick={() => handleDeleteUser(user.id)}>Delete</button>
</div>
))}
</div>
);
};
export default UsersList;API Reference
configureRequestService(config)
Configures the global request service.
Parameters:
config.apiClient: Your API client implementationconfig.toastService: Optional toast service for notificationsconfig.successMessages: Custom success messages
createControllers(config)
Creates controller functions for your slice.
Parameters:
config.storeName: Name of your store sliceconfig.endpoints: Object containing your API endpoints
createSliceWithCRUD(config)
Creates a Redux slice with CRUD operations.
Parameters:
config.name: Name of the sliceconfig.initialState: Initial state (usecreateInitialState<T>())config.customReducers: Your custom reducers
addControllerToSlice(slice, controllers)
Adds controller functions to your slice.
Parameters:
slice: Your created slicecontrollers: Object containing your controller functions
Available Controller Functions
getData: Get single data with cachinggetAllData: Get all data without paginationgetAsPagination: Get paginated datacreateOrUpdateData: Create or update datadeleteData: Delete dataputRequest: PUT request
State Structure
Your slice state will have the following structure:
interface SliceState<T> {
data: PaginatedResponse<T>;
allData: T;
loading: boolean;
error: any;
success: boolean;
getLoading: boolean;
getError: any;
PaginationLoading: boolean;
PaginationError: any;
itIsAsParams: boolean;
paramsData: any;
next_page: boolean;
}Advanced Usage
Custom Reducers
You can add custom reducers alongside the CRUD operations:
export const usersSlice = createSliceWithCRUD({
name: 'users',
initialState,
customReducers: {
updateUserName: (state, action) => {
const { id, name } = action.payload;
const user = state.allData.find((u: User) => u.id === id);
if (user) {
user.name = name;
user.updated_at = new Date().toISOString();
}
},
clearUsers: (state) => {
state.allData = [];
state.data.data = [];
}
}
});Error Handling
The package provides comprehensive error handling:
const UsersComponent = () => {
const { data, loading, error, getError, PaginationError } = useSelector(
(state: RootState) => state.users
);
if (error) {
return <div>Error: {error.message}</div>;
}
if (getError) {
return <div>Get Error: {getError.message}</div>;
}
if (PaginationError) {
return <div>Pagination Error: {PaginationError.message}</div>;
}
// Your component logic...
};Loading States
Different loading states for different operations:
const {
loading, // For create/update/delete operations
getLoading, // For get operations
PaginationLoading // For pagination operations
} = useSelector((state: RootState) => state.users);Pagination Support
The package includes built-in pagination support:
// Get paginated data
dispatch(getUsersAsPagination({ pageNumber: 1, perPage: 10 }));
// Access pagination info
const { data, pagination } = useSelector((state: RootState) => state.users);
console.log(`Page ${pagination.current_page} of ${pagination.last_page}`);API Reference
Types
InitialStateType<T>
interface InitialStateType<T> {
data: PaginatedResponse<T>;
allData: T;
loading: boolean;
error: any;
success: boolean;
getLoading: boolean;
getError: any;
PaginationLoading: boolean;
PaginationError: any;
itIsAsParams: boolean;
paramsData: any;
next_page: boolean;
}PaginatedResponse<T>
interface PaginatedResponse<T> {
data: T[];
pagination: {
current_page: number;
per_page: number;
total: number;
last_page: number;
from: number;
to: number;
next_page_url: string | null;
prev_page_url: string | null;
};
}Functions
configureRequestService(config)
Configures the global request service.
Parameters:
config.apiClient: Your API client implementationconfig.toastService: Optional toast service for notificationsconfig.successMessages: Custom success messages
createControllers(config)
Creates controller functions for your slice.
Parameters:
config.storeName: Name of your store sliceconfig.endpoints: Object containing your API endpoints
createSliceWithCRUD(config)
Creates a Redux slice with CRUD operations.
Parameters:
config.name: Name of the sliceconfig.initialState: Initial state (usecreateInitialState<T>())config.customReducers: Your custom reducers
addControllerToSlice(slice, controllers)
Adds controller functions to your slice.
Parameters:
slice: Your created slicecontrollers: Object containing your controller functions
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT
Support
If you find this package helpful, please consider:
- ⭐ Starring the repository
- 🐛 Reporting bugs
- 💡 Suggesting new features
- 📖 Improving the documentation
Changelog
See CHANGELOG.md for a list of changes and version history.
