Genesis Foundation Redux
foundation-redux
provides Redux Toolkit integration for Genesis components, offering a clean and efficient way to manage application state using the proven Redux pattern.
Background
This package was created to provide an alternative to foundation-store
by leveraging the power and ecosystem of Redux Toolkit. While foundation-store
implements a Redux-like pattern within the Genesis context, foundation-redux
provides direct bindings to Redux itself, allowing developers to benefit from:
- Vast Redux documentation and ecosystem
- Redux DevTools integration
- Proven patterns and best practices
- Extensive community support
- Built-in immutability handling
Why Choose foundation-redux over foundation-store?
Reduced Boilerplate
Foundation store requires manual immutability handling and custom event setup, while Redux Toolkit handles immutability automatically.
Foundation store example:
this.createListener<DeleteViewDerivedFieldPayload>(
StoreEvents.DeleteViewDerivedField,
({ view, field }) => {
const { [field]: fieldToDelete, ...rest } =
this.commit.genesisCreateConfig.views.views[view]?.derivedFields || {};
if (fieldToDelete) {
this.commit.genesisCreateConfig = {
...this.genesisCreateConfig,
views: {
views: {
...this.genesisCreateConfig.views.views,
[view]: {
...this.genesisCreateConfig.views.views[view],
derivedFields: {
...rest,
},
},
},
},
};
}
},
);
Redux Toolkit example:
deleteDerivedField(state, { payload: { view, field } }) {
delete state[view].derivedFields[field];
}
Ecosystem Benefits
- Redux DevTools: Built-in debugging and time-travel debugging
- Middleware: Extensive middleware ecosystem
- Entity Adapters: Auto-generated CRUD actions and selectors
- Serialization: Built-in support for local storage and hydration
Installation
To enable this module in your application, follow the steps below.
- Add
@genesislcap/foundation-redux
as a dependency in yourpackage.json
file. Whenever you change the dependencies of your project, ensure you run the$ npm run bootstrap
command again.
{
...
"dependencies": {
...
"@genesislcap/foundation-redux": "latest"
...
},
...
}
Usage
Basic Store Setup
import { createStore } from '@genesislcap/foundation-redux';
import { createSlice } from '@reduxjs/toolkit';
import { customElement, GenesisElement, observable } from '@genesislcap/web-core';
// Define your slices
const userSlice = createSlice({
name: 'user',
initialState: { name: '', email: '' },
reducers: {
setUser: (state, action) => {
state.name = action.payload.name;
state.email = action.payload.email;
},
clearUser: (state) => {
state.name = '';
state.email = '';
},
},
selectors: {
getUserName: (state) => state.name,
getUserEmail: (state) => state.email,
},
});
// Create the store
const { store, actions, selectors } = createStore([userSlice], {});
@customElement({
name: 'user-component',
template: html`<div>Hello ${(x) => x.userName}!</div>`,
})
export class UserComponent extends GenesisElement {
@observable userName = '';
connectedCallback() {
super.connectedCallback();
// Subscribe to store changes
store.subscribeKey(
(state) => state.user.name,
(state) => {
this.userName = state.user.name;
}
);
}
handleLogin() {
actions.user.setUser({ name: 'John Doe', email: 'john@example.com' });
}
}
Advanced Features
- Thunk Actions: Support for async operations
- Entity Adapters: Auto-generated CRUD operations
- DevTools: Full Redux DevTools integration
- Middleware: Custom middleware support
- Local Storage: Built-in persistence helpers
API Reference
createStore(slices, preloadedState)
Creates a Redux store with Genesis component integration.
Parameters:
slices
: Array of Redux Toolkit slicespreloadedState
: Initial state for the store
Returns:
store
: Proxied state object for reactive updatesactions
: Bound action creatorsselectors
: Bound selectorsdispatch
: Redux dispatch functionsubscribe
: Store subscription functionsubscribeKey
: Key-based subscription for performancenotify
: Manual notification trigger
Store Integration
The store automatically integrates with Genesis's Observable system, providing reactive updates when state changes. Components can subscribe to specific state changes using subscribeKey
for optimal performance.
Migration from foundation-store
If you're currently using foundation-store
, migration to foundation-redux
involves:
- Replace store creation: Use
createStore
instead of store fragments - Convert event handlers: Replace custom events with Redux actions
- Update subscriptions: Use
subscribeKey
instead of binding observers - Simplify state updates: Let Redux Toolkit handle immutability
API
You can find out more details in our API docs.