Line 96 of Router.js:
this.transitionManager = this.createTransitionManager();
all my inputs are defined at runtime I've confirmed, and this.createTransitionManager() is also defined.
After passing that line though, this.transitionManager is not defined, and the packaged application fails with:
Uncaught (in promise) TypeError: Cannot read property 'getCurrentLocation' of undefined(…) on line 99 of Router.js
Any ideas on why this might be the case?
What is the full stacktrace?
createTransitionManager @ Router.js:99
componentWillMount @ Router.js:106
performInitialMount @ ReactCompositeComponent.js:351
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
mountComponentIntoNode @ ReactMount.js:104
perform @ Transaction.js:140
batchedMountComponentIntoNode @ ReactMount.js:126
perform @ Transaction.js:140
batchedUpdates @ ReactDefaultBatchingStrategy.js:62
batchedUpdates @ ReactUpdates.js:97
_renderNewRootComponent @ ReactMount.js:320
_renderSubtreeIntoContainer @ ReactMount.js:401
render @ ReactMount.js:422
createStoreFunction @ index.js:129
module.exports../app/index.js.getStoredState.then @ index.js:187
Here also is a pastebin of the file: http://pastebin.com/a0pe7cNX
There's lots of empty lines in the file where I've removed a bunch of commented out code and replaced it with empty comments to keep things simple, but lined up to the original line numbers.
I am creating my store with an existing state, wrapped in a promise at line 187, where this call stack begins.
I have tried removing my createStoreFunction from the promise and also have tried not importing any existing state and just creating an empty one as the boilerplate does by default. The only difference is that I am rendering the
This method of creating store works fine in development, and has worked fine for production until at least the end of 2016, which is when I had last synced upstream prior to a few weeks ago.
I can't find any reason this should fail. I get the same results in all configurations.
I've tried now removing it from the function and running it almost identically to the default.
This is my production store config. It is slightly different than the stock, but like all the above, worked fine ~3 months ago, and I can't find any changes to the boilerplate that I would expect to create issues.
import { applyMiddleware, createStore, compose } from 'redux';
import { responsiveStoreEnhancer } from 'redux-responsive';
import thunk from 'redux-thunk';
import { routerMiddleware, push } from 'react-router-redux';
import rootReducer from '../reducers';
import storage from '../utils/storage';
import onExitStorage from '../utils/onExitStorage';
import * as noteActions from '../actions/notes_actions';
var hashHistory = require('react-router').hashHistory;
const actionCreators = {
...noteActions,
push,
};
const router = routerMiddleware(hashHistory);
const enhancer = compose(
responsiveStoreEnhancer,
applyMiddleware(thunk, router),
storage(),
onExitStorage(),
);
export default function configureStore(initialState: Object | void) {
return createStore(rootReducer, initialState, enhancer);
}
Within react-router, this.props.history is undefined
I have no idea what could cause this.
Should process.env.NODE_ENV be defined in the packaged version? It is undefined, which seems proper, but since I had to package it myself I'm wondering if it has anything to do with NODE_ENV being wrong.
I believe it should be production because of the define plugin. Also did you resolve this? If so, please close. Makes it easier for me to keep track of issues. Thanks!
@amilajack I have not been able to resolve this one yet. It may be due to the workaround I had to use in #816
I will attempt to resolve this again soon and update here.
It's ended up being one of those tough ones that you have to leave and come back to, lest you give up all hope.
So in my index.js store and historyare both defined when I run this in the index.js
store = configureStore(myAppState);
history = syncHistoryWithStore(hashHistory, store);
render(
<AppContainer>
<Root store={store} history={history} />
</AppContainer>,
document.getElementById('root')
);
When I examine the script running in the root.js file moments later, they are both undefinedthere.
Only happens in production. I confirmed process.env.NODE_ENV is supposed to be undefinedin a working perfect copy of the repo, so that's not the issue.
I don't know if this is somehow related to my not being able to build via NPM scripts or entirely unrelated. Any thoughts?
All that changed was the boilerplate, and honestly not very much. The change that must have broken it is the addition of the root.js file which I was not using before.
Absolutely no idea why the values are suddenly undefined when it passed off to Root.
I will try to create a small demo using createTransitionManager() and see if I run into the same issue.
I think the root of the issue is really in passing values into root.js and I just didn't realize prior because I was unable to debug in that file by setting a breakpoint. After repackaging it with a debugger in root.js I find the values to be undefined there, which I believe all occurs prior to createTransitionManager() being run
What method are you using to debug the production build?
I've enabled the devTools window to open and changed the sourcemaps mode to inline instead of cheap-eval
Not sure how well that answers your question, but that's what I've been doing to try and pinpoint the cause.
After syncing with upstream again (commit f4dc6f2917f21bfdc7d58d2830421af9c2260201), I now see the error in both production and development and the error is that I am passing the wrong version of history.
In reality, history is not making it into my Root element, even if I move Root to the index.js.
What does work is moving Root to the index.js and not passing store and history, but instead pulling them in from outside the Root scope.
const Root = () => {
return (
<Provider store={store}>
<Router key={Math.random()} history={history} routes={myRoutes} />
</Provider>
);
}
store = configureStore(appState);
history = syncHistoryWithStore(hashHistory, store);
render(
<AppContainer>
<Root store={store} history={history} />
</AppContainer>,
document.getElementById('root')
);
Unfortunately this breaks hot reloading, though it only throws an error about <Root> being in the same file sometimes. Any ideas why this may be? I'm thinking possibly a bug in <AppContainer>? I don't know what to make of it.
Anyone have any thoughts on this? It really breaks the whole boilerplate for me since I have to fully reload any time I make a typo in my code that causes a compile error.
I know this isn't replicated in the master version, but I am doing everything exactly the same way and getting this bug, which is baffling. I've spent a good 14 hours on it now.
Do you have a minimal boilerplate that I can look through? I remember asking you for this before but I may have missed your response.
I may have missed you asking. I'll try to put something together. I supposed it shouldn't be terribly difficult to slice apart my current repo since it's at the top level.
@Slapbox it would be easier for me if you could clone the repo and make the minimal amount of changes to the fresh clone in order to reproduce the error. Also sorry for the late responses. Have a couple midterms coming up 😢
@amilajack it amazes me you are not even out of school.
I managed to resolve the issue, though I didn't exactly manage to figure out what the issue was. It was something in my store I think? I'm really not sure unfortunately. Thanks very much for your help.
Okay so fixing this issue, here's the code and how it works:
index.js
import _ from 'lodash';
import React from 'react';
import { Provider } from 'react-redux';
import { render } from 'react-dom';
import { syncHistoryWithStore } from 'react-router-redux';
import { Router, hashHistory } from 'react-router';
import { AppContainer } from 'react-hot-loader';
import configureStore from './store/configureStore';
import myRoutes from './routes';
import Root from './containers/Root';
function ProductionRoot() {
return (
<Provider store={store}>
<Router key={Math.random()} history={history} routes={myRoutes} />
</Provider>
);
}
function createStoreFunction() {
store = configureStore();
history = syncHistoryWithStore(hashHistory, store);
render(
<AppContainer>
{(process.env.NODE_ENV != 'development') ? <ProductionRoot store={store} history={history} /> : <Root store={store} history={history} /> }
</AppContainer>,
document.getElementById('root')
);
if (module.hot) {
module.hot.accept('./containers/Root', () => {
const NextRoot = require('./containers/Root'); // eslint-disable-line global-require
render(
<AppContainer>
<NextRoot store={store} history={history} />
</AppContainer>,
document.getElementById('root')
);
});
}
In my particular case, in production, store and history are undefined, unless root is within the same file, and the store and history are not explicitly passed in. This is a workaround for that issue if anyone else runs into it.
Most helpful comment
Okay so fixing this issue, here's the code and how it works:
index.js
In my particular case, in production,
storeandhistoryare undefined, unlessrootis within the same file, and the store and history are not explicitly passed in. This is a workaround for that issue if anyone else runs into it.