Closed kristian2x closed 4 years ago
I also tried console.logging state inside getUserContext but it didn't fire, maybe that's a separate problem?
I faced the same issue. My project is a monorepo, that the redux-store logic is in a separated package (yarn-workspace base packages) than my CRA based app.
The CRA src/index.js
:
import React from 'react';
import ReactDOM from 'react-dom';
import * as Sentry from '@sentry/browser';
import App from './app';
Sentry.init({});
ReactDOM.render(
<App />,
document.getElementById('root')
);
src/app.js
:
import configureStore from '@package/store/configure-store';
const store = configureStore({});
const App = ()=> {
return <div>The app</div>;
}
@package/store/configure-store.js
:
import { applyMiddleware, createStore } from 'redux';
import createSentryMiddleware from 'redux-sentry-middleware';
import * as Sentry from '@sentry/browser';
export default function configureStore(initialState = {}) {
const sentryMiddleware = createSentryMiddleware(Sentry, {
getUserContext: (state) => {
console.log(state);
return {};
},
});
}
But the console.log(state);
never called. The issue is because of calling Sentry.init({});
after const store = configureStore({});
which somehow make the below code of this module not effecting the Sentry after calling init
.
redux-sentry-middleware/blob/master/src/main.js
:
Sentry.configureScope(scope => {
scope.addEventProcessor((event, hint) => {
But the below part will be called because it'll be called after the sentry init as it'll add a breadcrumb for each redux action.
redux-sentry-middleware/blob/master/src/main.js
:
return next => action => {
if (filterBreadcrumbActions(action)) {
Sentry.addBreadcrumb({
This cannot be fixed by putting the Sentry.init({});
call before import App from './app';
because imports will be hoisted You Don't Know JS Yet: ES.Next & Beyond - Chapter 3: Organization. To fix this, you can put the sentry initialize logic into a separate file and import that file before importing App
component. Like below:
src/sentry.js
:
import * as Sentry from '@sentry/browser';
Sentry.init({});
src/index.js
:
import React from 'react';
import ReactDOM from 'react-dom';
import './sentry';
import App from './app';
ReactDOM.render(
<App />,
document.getElementById('root')
);
Thanks A LOT for the thorough response, I'll try your solution and report back!
I had my Senty.init
in my index as well before I added this middleware, after moving the init into my store before redux middleware, everything was working as expected.
As @alirdn stated, imports are hosisted (which I didn't know so thanks for that ) so the code in your store is running before the init in the index file.
Here's my basic store file
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import reduxPromise from 'redux-promise';
import { createStore, applyMiddleware, compose } from 'redux';
import reducers from './Reducers';
import * as Sentry from '@sentry/browser';
import createSentryMiddleware from 'redux-sentry-middleware';
Sentry.init({
dsn: YOUR_KEY_HERE,
beforeSend(event) {
if (event.exception) {
Sentry.showReportDialog({ eventId: event.event_id });
}
return event;
}
});
const middleware = [reduxPromise, thunk, createSentryMiddleware(Sentry)];
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducers,
composeEnhancers(applyMiddleware(...middleware))
);
export default store;
And in my index.js
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Thanks @alirdn your solution worked.
I have
Sentry.init()
in my index.js. Do I have to re-init Sentry in my store.js where I appy the createSentryMiddleware()? or can I just pass the imported sentry (import * as Sentry from "@sentry/browser";
)currently my store.js looks like this (while I do see the fired actions in sentry I get no user context):