Skip to content

Commit

Permalink
fix(ReduxQuerySync): Allow unsubscribing from ReduxQuerySync (#2692)
Browse files Browse the repository at this point in the history
  • Loading branch information
grafakus authored Nov 15, 2023
1 parent 31b5d62 commit 1d93882
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 113 deletions.
29 changes: 16 additions & 13 deletions public/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Sidebar } from '@pyroscope/components/Sidebar';
import { TenantWall } from '@pyroscope/components/TenantWall';
import { useSelectFirstApp } from '@pyroscope/hooks/useAppNames';
import '@pyroscope/jquery-import';
import { Provider } from 'react-redux';
import store from '@pyroscope/redux/store';
import './sass/profile.scss';
import '@szhsin/react-menu/dist/index.css';
import Notifications from '@pyroscope/ui/Notifications';
import { Router, Switch, Route } from 'react-router-dom';
import { ROUTES } from '@pyroscope/pages/routes';
import { SingleView } from '@pyroscope/pages/SingleView';
import { ComparisonView } from '@pyroscope/pages/ComparisonView';
import { ExploreView } from '@pyroscope/pages/ExploreView';
import { DiffView } from '@pyroscope/pages/DiffView';
import { Sidebar } from '@pyroscope/components/Sidebar';
import { TenantWall } from '@pyroscope/components/TenantWall';
import { ExploreView } from '@pyroscope/pages/ExploreView';
import { SingleView } from '@pyroscope/pages/SingleView';
import { ROUTES } from '@pyroscope/pages/routes';
import store from '@pyroscope/redux/store';
import Notifications from '@pyroscope/ui/Notifications';
import { history } from '@pyroscope/util/history';
import { useSelectFirstApp } from '@pyroscope/hooks/useAppNames';
import '@szhsin/react-menu/dist/index.css';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { Route, Router, Switch } from 'react-router-dom';
import { useReduxQuerySync } from './redux/useReduxQuerySync';
import './sass/profile.scss';

const container = document.getElementById('reactRoot') as HTMLElement;
const root = ReactDOM.createRoot(container);

function App() {
useReduxQuerySync();

useSelectFirstApp();

return (
Expand Down
102 changes: 2 additions & 100 deletions public/app/redux/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,13 @@ import {

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Until we rewrite FlamegraphRenderer in typescript this will do
import ReduxQuerySync from 'redux-query-sync';
import { configureStore, combineReducers, Middleware } from '@reduxjs/toolkit';

import tracingReducer, {
actions as tracingActions,
} from '@pyroscope/redux/reducers/tracing';
import { history } from '@pyroscope/util/history';
import tracingReducer from '@pyroscope/redux/reducers/tracing';

import settingsReducer from './reducers/settings';
import userReducer from './reducers/user';
import {
continuousReducer,
actions as continuousActions,
} from './reducers/continuous';
import { continuousReducer } from './reducers/continuous';
import serviceDiscoveryReducer from './reducers/serviceDiscovery';
import adhocReducer from '@pyroscope/redux/reducers/adhoc';
import uiStore, { persistConfig as uiPersistConfig } from './reducers/ui';
Expand Down Expand Up @@ -79,97 +72,6 @@ const store = configureStore({

export const persistor = persistStore(store);

// This is a bi-directional sync between the query parameters and the redux store
// It works as follows:
// * When URL query changes, It will dispatch the action
// * When the store changes (the field set in selector), the query param is updated
// For more info see the implementation at
// https://github.com/Treora/redux-query-sync/blob/master/src/redux-query-sync.js
ReduxQuerySync({
store,
params: {
from: {
defaultValue: 'now-1h',
selector: (state: RootState) => state.continuous.from,
action: continuousActions.setFrom,
},
until: {
defaultValue: 'now',
selector: (state: RootState) => state.continuous.until,
action: continuousActions.setUntil,
},
leftFrom: {
defaultValue: 'now-1h',
selector: (state: RootState) => state.continuous.leftFrom,
action: continuousActions.setLeftFrom,
},
leftUntil: {
defaultValue: 'now-30m',
selector: (state: RootState) => state.continuous.leftUntil,
action: continuousActions.setLeftUntil,
},
rightFrom: {
defaultValue: 'now-30m',
selector: (state: RootState) => state.continuous.rightFrom,
action: continuousActions.setRightFrom,
},
rightUntil: {
defaultValue: 'now',
selector: (state: RootState) => state.continuous.rightUntil,
action: continuousActions.setRightUntil,
},
query: {
defaultvalue: '',
selector: (state: RootState) => {
const {
continuous: { query },
} = state;
// Only sync the query URL parameter if it is actually set to something
// Otherwise `?query=` will always be appended to the URL
if (query !== '') {
return query;
}
return undefined;
},
action: continuousActions.setQuery,
},
queryID: {
defaultvalue: '',
selector: (state: RootState) => state.tracing.queryID,
action: tracingActions.setQueryID,
},
rightQuery: {
defaultvalue: '',
selector: (state: RootState) => state.continuous.rightQuery,
action: continuousActions.setRightQuery,
},
leftQuery: {
defaultvalue: '',
selector: (state: RootState) => state.continuous.leftQuery,
action: continuousActions.setLeftQuery,
},
maxNodes: {
defaultValue: '0',
selector: (state: RootState) => state.continuous.maxNodes,
action: continuousActions.setMaxNodes,
},
groupBy: {
defaultValue: '',
selector: (state: RootState) =>
state.continuous.tagExplorerView.groupByTag,
action: continuousActions.setTagExplorerViewGroupByTag,
},
groupByValue: {
defaultValue: '',
selector: (state: RootState) =>
state.continuous.tagExplorerView.groupByTagValue,
action: continuousActions.setTagExplorerViewGroupByTagValue,
},
},
initialTruth: 'location',
replaceState: false,
history,
});
export default store;

// Infer the `RootState` and `AppDispatch` types from the store itself
Expand Down
104 changes: 104 additions & 0 deletions public/app/redux/useReduxQuerySync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { useEffect } from 'react';
import { actions as tracingActions } from '@pyroscope/redux/reducers/tracing';
import { history } from '@pyroscope/util/history';
import ReduxQuerySync from 'redux-query-sync';
import { actions as continuousActions } from './reducers/continuous';
import store, { RootState } from './store';

function setupReduxQuerySync() {
// This is a bi-directional sync between the query parameters and the redux store
// It works as follows:
// * When URL query changes, It will dispatch the action
// * When the store changes (the field set in selector), the query param is updated
// For more info see the implementation at
// https://github.com/Treora/redux-query-sync/blob/master/src/redux-query-sync.js
return ReduxQuerySync({
store,
params: {
from: {
defaultValue: 'now-1h',
selector: (state: RootState) => state.continuous.from,
action: continuousActions.setFrom,
},
until: {
defaultValue: 'now',
selector: (state: RootState) => state.continuous.until,
action: continuousActions.setUntil,
},
leftFrom: {
defaultValue: 'now-1h',
selector: (state: RootState) => state.continuous.leftFrom,
action: continuousActions.setLeftFrom,
},
leftUntil: {
defaultValue: 'now-30m',
selector: (state: RootState) => state.continuous.leftUntil,
action: continuousActions.setLeftUntil,
},
rightFrom: {
defaultValue: 'now-30m',
selector: (state: RootState) => state.continuous.rightFrom,
action: continuousActions.setRightFrom,
},
rightUntil: {
defaultValue: 'now',
selector: (state: RootState) => state.continuous.rightUntil,
action: continuousActions.setRightUntil,
},
query: {
defaultvalue: '',
selector: (state: RootState) => {
const {
continuous: { query },
} = state;
// Only sync the query URL parameter if it is actually set to something
// Otherwise `?query=` will always be appended to the URL
if (query !== '') {
return query;
}
return undefined;
},
action: continuousActions.setQuery,
},
queryID: {
defaultvalue: '',
selector: (state: RootState) => state.tracing.queryID,
action: tracingActions.setQueryID,
},
rightQuery: {
defaultvalue: '',
selector: (state: RootState) => state.continuous.rightQuery,
action: continuousActions.setRightQuery,
},
leftQuery: {
defaultvalue: '',
selector: (state: RootState) => state.continuous.leftQuery,
action: continuousActions.setLeftQuery,
},
maxNodes: {
defaultValue: '0',
selector: (state: RootState) => state.continuous.maxNodes,
action: continuousActions.setMaxNodes,
},
groupBy: {
defaultValue: '',
selector: (state: RootState) =>
state.continuous.tagExplorerView.groupByTag,
action: continuousActions.setTagExplorerViewGroupByTag,
},
groupByValue: {
defaultValue: '',
selector: (state: RootState) =>
state.continuous.tagExplorerView.groupByTagValue,
action: continuousActions.setTagExplorerViewGroupByTagValue,
},
},
initialTruth: 'location',
replaceState: false,
history,
});
}

export function useReduxQuerySync() {
useEffect(setupReduxQuerySync, []);
}

0 comments on commit 1d93882

Please sign in to comment.