Observable store
Classes
- ObservableStore ⇐
Observable
Functions
- slice(store, options) ⇒
Object
Creates a slice of the store with its own state and actions, namespaced to avoid conflicts.
- store(initialState, [options]) ⇒
ObservableStore
This function creates a new instance of ObservableStore with the provided initial state and enhances it with localStorage support if enabled. The store's state will be automatically persisted to and loaded from localStorage, using the provided name as the key. The
localStorage
option enables this behavior and can be toggled off if persistence is not needed.
ObservableStore ⇐ Observable
Kind: global class
Extends: Observable
- ObservableStore ⇐
Observable
- new ObservableStore()
- instance
- static
new ObservableStore()
This class is used to create a store that can be observed for changes. It supports registering actions and middleware, making it flexible for various use cases.
Example
// Creating a store with initial state and registering actions
const CartStore = cami.store({
cartItems: [],
});
CartStore.register('add', (state, product) => {
const cartItem = { ...product, cartItemId: Date.now() };
state.cartItems.push(cartItem);
});
CartStore.register('remove', (state, product) => {
state.cartItems = state.cartItems.filter(item => item.cartItemId !== product.cartItemId);
});
// Using middleware for logging
const loggerMiddleware = (context) => {
console.log(`Action ${context.action} was dispatched with payload:`, context.payload);
};
CartStore.use(loggerMiddleware);
observableStore.dispatch(action, [payload])
Dispatches an action to update the store's state.
Kind: instance method of ObservableStore
Param | Type | Description |
---|---|---|
action | string | function |
The action type (string) or action creator (function). |
[payload] | any |
The optional payload object to pass to the reducer. |
Example
// Dispatching a simple action
store.dispatch('increment');
// Dispatching an action with payload
store.dispatch('addItem', { id: 1, name: 'New Item' });
ObservableStore.use(middleware)
This method registers a middleware function to be used with the store. Useful if you like redux-style middleware.
Kind: static method of ObservableStore
Param | Type | Description |
---|---|---|
middleware | function |
The middleware function to use |
Example
const loggerMiddleware = (context) => {
console.log(`Action ${context.action} was dispatched with payload:`, context.payload);
};
CartStore.use(loggerMiddleware);
ObservableStore.getState() ⇒ Object
Retrieves the current state of the store. This method is crucial in asynchronous operations or event-driven environments to ensure the most current state is accessed, as the state might change frequently due to user interactions or other asynchronous updates.
Kind: static method of ObservableStore
Returns: Object
- - The current state of the store.
ObservableStore.register(action, reducer)
This method registers a reducer function for a given action type. Useful if you like redux-style reducers.
Kind: static method of ObservableStore
Throws:
Error
- Throws an error if the action type is already registered
Param | Type | Description |
---|---|---|
action | string |
The action type |
reducer | function |
The reducer function for the action |
Example
// Creating a store with initial state and registering actions
const CartStore = cami.store({
cartItems: [],
});
CartStore.register('add', (state, product) => {
const cartItem = { ...product, cartItemId: Date.now() };
state.cartItems.push(cartItem);
});
CartStore.register('remove', (state, product) => {
state.cartItems = state.cartItems.filter(item => item.cartItemId !== product.cartItemId);
});
ObservableStore.onPatch(key, callback)
Registers a callback to be invoked whenever patches are applied to the specified state key.
Kind: static method of ObservableStore
Param | Type | Description |
---|---|---|
key | string |
The state key to listen for patches. |
callback | function |
The callback to invoke when patches are applied. |
Example
ObservableStore.applyPatch(patches)
Applies the given patches to the store's state.
Kind: static method of ObservableStore
Param | Type | Description |
---|---|---|
patches | Array |
The patches to apply to the state. |
Example
const patches = [{ op: 'replace', path: ['posts', 0, 'title'], value: 'New Title' }];
appStore.applyPatch(patches);
ObservableStore.query(queryName, config)
Registers a query with the given configuration. This method sets up the query with the provided options and handles refetching based on various triggers like window focus, reconnect, and intervals.
Kind: static method of ObservableStore
Param | Type | Default | Description |
---|---|---|---|
queryName | string |
The name of the query to register. | |
config | Object |
The configuration object for the query. | |
config.queryKey | string | Array |
The unique key for the query. | |
config.queryFn | function |
The function to fetch data for the query. | |
[config.staleTime] | number |
0 |
The time in milliseconds before the query is considered stale. |
[config.refetchOnWindowFocus] | boolean |
false |
Whether to refetch the query on window focus. |
[config.refetchInterval] | number | null |
|
The interval in milliseconds to refetch the query. |
[config.refetchOnReconnect] | boolean |
true |
Whether to refetch the query on reconnect. |
[config.gcTime] | number |
300000 |
The time in milliseconds before garbage collecting the query. |
[config.retry] | number |
1 |
The number of retry attempts for the query. |
[config.retryDelay] | function |
The function to calculate the delay between retries. | |
[config.onSuccess] | function |
The callback function to execute when the query succeeds. Receives a context object with result , state , actions , mutations , and invalidateQueries . |
|
[config.onError] | function |
The callback function to execute when the query fails. Receives a context object with error , state , actions , mutations , and invalidateQueries . |
|
[config.actions] | Object |
this.actions |
The actions available in the store. |
Example
appStore.register('setPosts', (state, posts) => {
state.posts = posts;
});
appStore.query('fetchPosts', {
queryKey: 'posts',
queryFn: () => fetch('https://api.camijs.com/posts').then(res => res.json()),
onSuccess: (ctx) => {
ctx.actions.setPosts(ctx.result);
},
onError: (ctx) => {
// console.error('Query failed:', ctx.error);
}
});
ObservableStore.fetch(queryName, ...args) ⇒ Promise
Fetches data for the given query name. If the data is cached and not stale, it returns the cached data. Otherwise, it fetches new data using the query function. Supports retry logic and calls lifecycle hooks.
Kind: static method of ObservableStore
Returns: Promise
- A promise that resolves to the query result.
Param | Type | Description |
---|---|---|
queryName | string |
The name of the query to fetch. |
...args | any |
The arguments to pass to the query function. |
Example
ObservableStore.invalidateQueries(queryName)
Invalidates the cache and any associated intervals or event listeners for a given query name.
Kind: static method of ObservableStore
Param | Type | Description |
---|---|---|
queryName | string |
The name of the query to invalidate. |
ObservableStore.mutation(mutationName, config)
Registers a mutation with the given configuration. This method sets up the mutation with the provided options and handles the mutation lifecycle.
Kind: static method of ObservableStore
Param | Type | Default | Description |
---|---|---|---|
mutationName | string |
The name of the mutation to register. | |
config | Object |
The configuration object for the mutation. | |
config.mutationFn | function |
The function to perform the mutation. | |
[config.onMutate] | function |
The function to be called before the mutation is performed. | |
[config.onError] | function |
The function to be called if the mutation encounters an error. | |
[config.onSuccess] | function |
The function to be called if the mutation is successful. | |
[config.onSettled] | function |
The function to be called after the mutation has either succeeded or failed. | |
[config.actions] | Object |
this.actions |
The actions available in the store. |
[config.queries] | Object |
this.queries |
The queries available in the store. |
Example
appStore.mutation('deletePost', {
mutationFn: (id) => fetch(`https://api.camijs.com/posts/${id}`, { method: 'DELETE' }).then(res => res.json()),
onMutate: (context) => {
context.actions.setPosts(context.state.posts.filter(post => post.id !== context.args[0]));
},
onError: (context) => {
context.actions.setPosts(context.previousState.posts);
},
onSuccess: (context) => {
console.log('Mutation successful:', context);
},
onSettled: (context) => {
console.log('Mutation settled');
context.invalidateQueries('posts');
}
});
appStore.mutate('deletePost', id);
ObservableStore.mutate(mutationName, ...args) ⇒ Promise
Performs the mutation with the given name and arguments. This method handles the mutation lifecycle, including optimistic updates, success handling, and error handling.
Kind: static method of ObservableStore
Returns: Promise
- A promise that resolves to the mutation result.
Param | Type | Description |
---|---|---|
mutationName | string |
The name of the mutation to perform. |
...args | any |
The arguments to pass to the mutation function. |
Example
// Define a mutation named 'deletePost'
appStore.mutation('deletePost', {
// The function that performs the actual mutation logic
mutationFn: (id) => fetch(`https://api.camijs.com/posts/${id}`, { method: 'DELETE' }).then(res => res.json()),
// Optional: Optimistically update the state before the mutation
onMutate: (context) => {
context.actions.setPosts(context.state.posts.filter(post => post.id !== context.args[0]));
},
// Optional: Handle errors during mutation
onError: (context) => {
context.actions.setPosts(context.previousState.posts);
},
// Optional: Perform actions after a successful mutation
onSuccess: (context) => {
console.log('Mutation successful:', context);
},
// Optional: Perform actions after the mutation is settled (success or error)
onSettled: (context) => {
console.log('Mutation settled');
context.invalidateQueries('posts');
}
});
// Execute the 'deletePost' mutation with a post ID
appStore.mutate('deletePost', 1);
slice(store, options) ⇒ Object
Creates a slice of the store with its own state and actions, namespaced to avoid conflicts.
Kind: global function
Returns: Object
- - An object containing the action methods for the slice, including getState, actions, queries, mutations, and subscribe methods.
Param | Type | Description |
---|---|---|
store | Object |
The main store instance. |
options | Object |
The options for creating the slice. |
options.name | string |
The name of the slice. |
options.state | Object |
The initial state of the slice. |
options.actions | Object |
The actions for the slice. |
[options.queries] | Object |
The queries for the slice. |
[options.mutations] | Object |
The mutations for the slice. |
Example
const appStore = store({
// Initial state for other parts of the application
});
const postsSlice = slice(appStore, {
name: 'posts',
state: [
{ id: 1, title: 'First Post' },
{ id: 2, title: 'Second Post' }
],
actions: {
updatePost: (state, { id, title }) => {
const postIndex = state.findIndex(post => post.id === id);
if (postIndex !== -1) {
state[postIndex].title = title;
}
}
}
});
// Accessing the slice's state
postsSlice.getState();
// Dispatching actions
postsSlice.actions.updatePost({ id: 1, title: 'Updated Title' });
// Subscribing to state changes
const unsubscribe = postsSlice.subscribe(state => {
console.log('Posts slice state changed:', state);
});
// Unsubscribe when no longer needed
unsubscribe();
store(initialState, [options]) ⇒ ObservableStore
This function creates a new instance of ObservableStore with the provided initial state and enhances it with localStorage support if enabled. The store's state will be automatically persisted to and loaded from localStorage, using the provided name as the key. The localStorage
option enables this behavior and can be toggled off if persistence is not needed.
Kind: global function
Returns: ObservableStore
- A new instance of ObservableStore with the provided initial state, enhanced with localStorage if enabled.
Param | Type | Default | Description |
---|---|---|---|
initialState | Object |
The initial state of the store. | |
[options] | Object |
Configuration options for the store. | |
[options.localStorage] | boolean |
true |
Whether to use localStorage for state persistence. |
[options.name] | string |
"'cami-store'" |
The name of the store to use as the key in localStorage. |
[options.expiry] | number |
86400000 |
The time in milliseconds until the stored state expires (default is 24 hours). |
Example