# Stockage de données
SmartCommon propose plusieurs solutions pour le stockage de données côté client :
* ''useGlobalStates'' : état global avec persistance automatique (localStorage/sessionStorage)
* ''useStates'' : état local réactif avec path notation
* ''useDb'' : base de données IndexedDB via Dexie
Documentation [IndexedDB](https://developer.mozilla.org/fr/docs/Web/API/IndexedDB_API)
Documentation [Dexie](https://dexie.org/)
Documentation [Redux Toolkit](https://redux-toolkit.js.org/)
## useGlobalStates (recommandé)
Le hook ''useGlobalStates'' fournit un état global avec persistance automatique. C'est la méthode recommandée pour les données utilisateur (session, préférences, etc.).
### Utilisation basique
```
import { useGlobalStates } from '@cap-rel/smartcommon';
export const MyComponent = () => {
const gst = useGlobalStates();
// Lire une valeur
const user = gst.get('user');
// Écrire dans localStorage (persistant)
const login = (userData) => {
gst.local.set('user', userData);
};
// Écrire dans sessionStorage (session uniquement)
const setTempData = (data) => {
gst.session.set('tempData', data);
};
// Supprimer une valeur
const logout = () => {
gst.unset('user');
};
return (
{user ? `Bonjour ${user.name}` : 'Non connecté'}
);
};
```
### Méthodes disponibles
^ Méthode ^ Description ^
| ''gst.get(path)'' | Récupère une valeur par son chemin |
| ''gst.local.set(path, value)'' | Stocke dans localStorage (persistant) |
| ''gst.session.set(path, value)'' | Stocke dans sessionStorage (session) |
| ''gst.unset(path)'' | Supprime une valeur |
| ''gst.values'' | Objet contenant toutes les valeurs |
### Path notation
Vous pouvez accéder aux données imbriquées avec la notation par points :
```
// Définir des données imbriquées
gst.local.set('user.preferences.theme', 'dark');
gst.local.set('user.preferences.language', 'fr');
// Lire des données imbriquées
const theme = gst.get('user.preferences.theme'); // 'dark'
const prefs = gst.get('user.preferences'); // { theme: 'dark', language: 'fr' }
```
## useStates (état local)
Le hook ''useStates'' fournit un état local réactif avec la même API que ''useGlobalStates''.
```
import { useStates } from '@cap-rel/smartcommon';
export const MyForm = () => {
const st = useStates({
initialStates: {
name: '',
email: '',
errors: {}
},
debug: true // affiche les changements dans la console
});
const handleChange = (field, value) => {
st.set(field, value);
};
const validate = () => {
if (!st.get('name')) {
st.set('errors.name', 'Le nom est requis');
}
};
return (
);
};
```
### Méthodes disponibles
^ Méthode ^ Description ^
| ''st.get(path)'' | Récupère une valeur |
| ''st.set(path, value)'' | Définit une valeur |
| ''st.unset(path)'' | Supprime une valeur |
| ''st.values'' | Objet contenant toutes les valeurs |
| ''st.states'' | Alias de values |
### Manipulation de tableaux
```
const st = useStates({ initialStates: { items: [] } });
// Ajouter un élément (push)
st.set('items[]', { id: 1, name: 'Item 1' });
// Modifier un élément par index
st.set('items[0].name', 'Item modifié');
// Supprimer un élément par index
st.unset('items[0]');
```
## useDb (IndexedDB)
Pour stocker de grandes quantités de données ou des données structurées complexes, utilisez ''useDb'' basé sur Dexie.
```
import { useDb } from '@cap-rel/smartcommon';
// Définir la base de données
const db = useDb({
name: 'myApp',
version: 1,
stores: {
items: 'id++, name, category, createdAt',
categories: 'id++, name'
},
debug: true
});
export const ItemsManager = () => {
const [items, setItems] = useState([]);
// Charger les items
useEffect(() => {
db.items.toArray().then(setItems);
}, []);
// Ajouter un item
const addItem = async (item) => {
const id = await db.items.add(item);
console.log('Item ajouté avec id:', id);
};
// Modifier un item
const updateItem = async (id, changes) => {
await db.items.update(id, changes);
};
// Supprimer un item
const deleteItem = async (id) => {
await db.items.delete(id);
};
// Requête avec filtre
const getByCategory = async (category) => {
return db.items.where('category').equals(category).toArray();
};
return (/* ... */);
};
```
### Fonctionnalités automatiques
''useDb'' ajoute automatiquement :
* ''createdAt'' : timestamp de création
* ''updatedAt'' : timestamp de dernière modification
* Table ''logs'' : journal de toutes les opérations (create, update, delete)
### Requêtes Dexie
```
// Tous les items
const all = await db.items.toArray();
// Par clé primaire
const item = await db.items.get(1);
// Filtrer
const filtered = await db.items
.where('category')
.equals('electronics')
.toArray();
// Trier
const sorted = await db.items
.orderBy('createdAt')
.reverse()
.toArray();
// Limiter
const first10 = await db.items.limit(10).toArray();
// Compter
const count = await db.items.count();
```
## Redux (méthode classique)
Si vous préférez utiliser Redux directement, SmartCommon fournit ''ReduxProvider''.
### Créer un slice
```
// src/redux/reducers/sessionSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
data: JSON.parse(sessionStorage.getItem("session")) ?? null
};
const sessionSlice = createSlice({
name: "session",
initialState,
reducers: {
setSession(state, action) {
state.data = action.payload;
sessionStorage.setItem("session", JSON.stringify(action.payload));
},
unsetSession(state) {
state.data = null;
sessionStorage.removeItem("session");
}
},
});
export default sessionSlice.reducer;
export const { setSession, unsetSession } = sessionSlice.actions;
```
### Configurer le store
```
// src/redux/index.js
import sessionReducer from "./reducers/sessionSlice";
import { combineReducers } from "redux";
import { configureStore } from "@reduxjs/toolkit";
const rootReducer = combineReducers({
session: sessionReducer
});
export const reduxStore = configureStore({ reducer: rootReducer });
export * from "./reducers/sessionSlice";
```
### Utiliser dans les composants
```
import { useSelector, useDispatch } from "react-redux";
import { setSession, unsetSession } from "../../../redux";
export const MyComponent = () => {
const session = useSelector(state => state.session.data);
const dispatch = useDispatch();
const login = (data) => dispatch(setSession(data));
const logout = () => dispatch(unsetSession());
return (/* ... */);
};
```
## Comparaison des méthodes
^ Méthode ^ Cas d'usage ^ Persistance ^
| ''useGlobalStates'' | Session utilisateur, préférences | localStorage / sessionStorage |
| ''useStates'' | État de formulaire, UI locale | Mémoire (non persistant) |
| ''useDb'' | Grandes quantités de données, offline | IndexedDB |
| Redux | Applications complexes, middleware | Configurable |
Pour la plupart des cas, ''useGlobalStates'' et ''useStates'' suffisent. Utilisez ''useDb'' uniquement pour des besoins spécifiques (mode offline, grandes quantités de données).
## Voir aussi
* [[hooks|Hooks]] - Documentation complète des hooks
* [[requetes_api|Requêtes API]] - Combiner avec les appels API