Comments (6)
I'll like to add one use case for this feature. As Redux based application grows there are several solutions to make it load faster:
- have several apps
- code split modules/pages
In our company, we're doing 2. so in order to use the redux-beacon
we need to have the ability to lazy load the events reducers.
For initial app load we fetch only actions/thunks/components that are required for that page. When a user navigates to another page we lazy-load their required files.
If we are going to use redux-beacon
as is, we will introduce a dependency graph to all trackable actions that will cause including all that files with actions to the initial load chunk (we're using Webpack) and make the initial JS file quite big. So, having something similar to redux#replaceReducer will help to solve the issue.
from redux-beacon.
huh, interesting. Are you doing something like:
if user x, track these analytics, else if user y, track these analytics
from redux-beacon.
No. We need to modify the EventDefinitionsMap
in the application without rebuild. Sometimes we need to change an event definition and we just don't want to wait for a new release of our app to do that.
from redux-beacon.
The only solution I see now is to fetch the configuration from the server as JSON (instead of using your powerful EventDefinitionsMap) via XHR. And create my own meta reducer to apply static definitions declared in that JSON.
from redux-beacon.
Sorry for the late reply on this. Had a busy week work-wise last week, and am in the middle of a move so my evenings/weekends are a bit more busy than usual.
I'm not sold on adding support for this sort of behaviour to the main redux-beacon package. Mostly because it seems like a fairly unique use-case. Is that fair?
But...we should be able to design something pretty easily based on the existing createMiddleware
and createMetaReducer
functions.
Maybe something like:
const getEvents = (eventsMap: EventsMap | EventsMapper) =>
typeof eventsMap === 'function'
? action => flatten<EventDefinition>([eventsMap(action)])
: action => getEventsWithMatchingKey(eventsMap, action.type);
function createMiddlewareDynamic(
eventsMap: EventsMap | EventsMapper,
target: Target,
extensions: Extensions = {}
) {
// save the initial (default) events definitions map
let currentEventsMap = eventsMap;
// a function that we expose to update currentEventsMap
const updateEventsMap = (newEventsMap: EventsMap | EventsMapper) => {
currentEventsMap = newEventsMap;
};
// the middleware
const middleware = store => next => action => {
const prevState = store.getState();
const result = next(action);
const nextState = store.getState();
const events = createEvents(
getEvents(currentEventsMap)(action),
prevState,
action,
nextState
);
registerEvents(events, target, extensions, prevState, action, nextState);
return result;
};
return { middleware, updateEventsMap };
}
And you'd use the function like so:
const { middleware, updateEventsMap } = createMiddlewareDynamic(initialEventsMap, gtmTarget(), { logger })
// use updateEventsMap wherever
updateEventsMap(newEventsMap)
Also, the function above would require access to the following utility functions in the main redux-beacon package:
import createEvents from './create-events';
import getEventsWithMatchingKey from './get-events-with-matching-key';
import registerEvents from './register-events';
I don't think I expose these. So for now, if you want to test it out I would copy-paste the compiled versions of these functions. If you need help with that, let me know.
from redux-beacon.
Thanks all for the comments on this issue!
I'll share my implementation for code splitting in pure JS based on https://github.com/dbartholomae/redux-dynamic-modules-beacon
class EventsManager {
#eventsMaps = [];
getEventsMap = action => {
const eventsMapByAction = this.#eventsMaps
.map(eventMapOrMapper =>
typeof eventMapOrMapper === 'function'
? eventMapOrMapper(action)
: eventMapOrMapper[action.type],
)
.flat();
return eventsMapByAction;
};
addEventsMap(eventMapOrMapper) {
this.#eventsMaps.push(eventMapOrMapper);
}
removeEventsMap(eventMapOrMapper) {
this.#eventsMaps = this.#eventsMaps.filter(map => map !== eventMapOrMapper);
}
}
import { createMiddleware } from 'redux-beacon';
function createManageableMiddleware(eventsMap, target, extensions) {
const manager = new EventsManager();
manager.addEventsMap(eventsMap);
// Setup the event middleware
const middleware = createMiddleware(manager.getEventsMap, target, extensions);
return {
middleware,
manager,
};
}
//enhance store with manageable middleware + attach events manager to the redux store in configureStore func
store.eventsManager = manageableMiddleware.manager;
// hook for attach/detach events
import { useStore } from 'react-redux';
import { useEffect, useRef } from 'react';
import { isNull } from 'lodash';
function useEventsMap(eventsMap) {
const store = useStore();
const eventsMapWasAttached = useRef(null);
useEffect(() => {
if (isNull(eventsMapWasAttached.current)) {
store.eventsManager.addEventsMap(eventsMap);
eventsMapWasAttached.current = true;
console.log(`useEventsMap, events map attached:`, eventsMap);
}
return () => {
if (eventsMapWasAttached.current) {
store.eventsManager.removeEventsMap(eventsMap);
eventsMapWasAttached.current = null;
console.log(`useEventsMap, events map detached:`, eventsMap);
}
};
}, []);
}
//usage example
import {trackEvent} from "@redux-beacon/google-analytics-gtag";
const eventsMap = {
[ON_ACTION_TYPE_CONST_SUBMIT_THIS_EVENT]: trackEvent(() => {...}),
};
function SomeComponent(){
//on did mount life cycle attach events from this map, and detach it on unmount
useEventsMap(eventsMap);
return (
...
)
}
from redux-beacon.
Related Issues (20)
- Redux Beacon Google Tag Manager docu down HOT 2
- trackException() sending incorrect fields object HOT 2
- Support for react-native-google-analytics-bridge version 6 HOT 1
- How are we meant to test this? HOT 1
- [TypeScript] Add support for typings in EventDefinition HOT 3
- Documentation request: please remove the Github Pages docs HOT 3
- Documentation Bug: Broken links on readme.md HOT 1
- How to track external link when each link has its own metadata? HOT 3
- trackEvent eventDefinition not showing the correct parameters HOT 1
- Gtag, access user-id config inside redux-beacon, React HOT 3
- [Typescript] combineEvents forces invalid type HOT 1
- Error when trying to track e-commerce items in GA following documentation HOT 1
- Update docs for usage with React Native + Segment HOT 1
- Add Matomo (formerly Piwik) support HOT 2
- Integration with Redux Dynamic Modules HOT 1
- Distribute as ES module HOT 1
- IP anonymization with Google Analytics (gtag) HOT 2
- Any Event [*] is invoked for all events even though the exact key match present HOT 1
- @amplitude/analytics-browser support
- Offline storage doesn't persist events
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from redux-beacon.