Skip to content

Commit 5a110c3

Browse files
author
Krzysztof Borowy
committed
docs: writing storage backend
1 parent eae485a commit 5a110c3

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ todo
1616

1717
## Documentation
1818

19-
todo
19+
- [Creating a custom Storage backend](./packages/core/docs/Writing_Storage_Backend.md)
2020

2121
## Available storage backends
2222

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Authoring Storage Backend
2+
3+
To create custom storage, one must create a class that implements `IStorageBackend` interface.
4+
This contract makes sure that Core knows how to use it.
5+
6+
## Example
7+
8+
Let's create a storage backend for web, using `LocalStorage` API.
9+
10+
Start by adding `AsyncStorage` to your dependencies.
11+
12+
```bash
13+
$ yarn add @react-native-community/async-storage
14+
```
15+
16+
Then, create a class and implement `IStorageBackend` interface;
17+
18+
19+
```typescript
20+
21+
import { IStorageBackend, EmptyStorageModel, StorageOptions } from '@react-native-community/async-storage';
22+
23+
class WebStorage<T extends EmptyStorageModel = EmptyStorageModel> implements IStorageBackend<T> {
24+
25+
storage = window.localStorage;
26+
27+
async getSingle<K extends keyof T>(
28+
key: K,
29+
opts?: StorageOptions,
30+
): Promise<T[K] | null> {
31+
32+
return this.storage.getItem(key);
33+
}
34+
35+
async setSingle<K extends keyof T>(
36+
key: K,
37+
value: T[K],
38+
opts?: StorageOptions,
39+
): Promise<void> {
40+
return this.storage.setItem(key, value);
41+
}
42+
43+
async getMany<K extends keyof T>(
44+
keys: Array<K>,
45+
opts?: StorageOptions,
46+
): Promise<{[k in K]: T[k] | null}>{
47+
48+
return Promise.all(keys.map(k => this.storage.getItem(k)))
49+
}
50+
51+
async setMany<K extends keyof T>(
52+
values: Array<{[k in K]: T[k]}>,
53+
opts?: StorageOptions,
54+
): Promise<void>{
55+
56+
for(let keyValue of values){
57+
const key = Object.getOwnPropertyNames(keyValue)[0];
58+
if(!key) continue;
59+
this.storage.setItem(key, keyValue[key])
60+
}
61+
}
62+
63+
async removeSingle(key: keyof T, opts?: StorageOptions): Promise<void> {
64+
return this.storage.removeItem(key);
65+
}
66+
67+
async removeMany(keys: Array<keyof T>, opts?: StorageOptions): Promise<void> {
68+
for (let key in keys) {
69+
this.storage.removeItem(key);
70+
}
71+
}
72+
73+
async getKeys(opts?: StorageOptions): Promise<Array<keyof T>> {
74+
return Object.keys(this.storage);
75+
}
76+
77+
async dropStorage(opts?: StorageOptions): Promise<void> {
78+
const keys = await this.getKeys();
79+
await this.removeMany(keys);
80+
}
81+
}
82+
83+
export default WebStorage;
84+
```
85+
86+
### Notes
87+
88+
- Each function should be asynchronous - even if access to storage is not.
89+
- In `localStorage`, remember that __keys__ and __values__ are always `string` - it's up to you if you're going to stringify it or accept stringified arguments.
90+
- `opts` argument can be used to 'enhance' each call, for example, one could use it to decide if the stored value should be replaced:
91+
92+
```typescript
93+
94+
// in a class
95+
96+
async setSingle<K extends keyof T>(
97+
key: K,
98+
value: T[K],
99+
opts?: StorageOptions,
100+
): Promise<void> {
101+
102+
if(!opts.replaceCurrent) {
103+
const current = this.storage.getItem(key);
104+
if(!current){
105+
this.storage.setItem(key, value);
106+
}
107+
return;
108+
}
109+
110+
return this.storage.setItem(key, value);
111+
}
112+
113+
```

0 commit comments

Comments
 (0)