将 redux-devtools 与 jspm / system.js / babel 结合使用
Using redux-devtools with jspm / system.js / babel
将 jspm / system.js 与 Babel 转译器一起使用时,我在控制台中看到以下错误
Uncaught (in promise) Error: XHR error loading http://localhost:3000/jspm_packages/npm/redux-devtools@2.1.0/lib/react/themes/pop.js
Error loading http://localhost:3000/jspm_packages/npm/redux-devtools@2.1.0/lib/react/themes/pop.js as "./pop" from http://localhost:3000/jspm_packages/npm/redux-devtools@2.1.0/lib/react/themes/index.js
at r (http://localhost:3000/jspm_packages/system.js:4:10975)
at XMLHttpRequest.o.onreadystatechange (http://localhost:3000/jspm_packages/system.js:4:11500)
如果我注释掉 react/themes/index.js
中的那一行,我(正如预期的那样)不会再看到该错误。
不过,我确实看到了这个;
Uncaught (in promise) Error: Cannot read property 'hasOwnProperty' of undefined
Error loading http://localhost:3000/index.js
at Object.checkAndWarnForMutatedProps (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactElementValidator.js:157:27)
at Object.ReactReconciler.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactReconciler.js:13:31)
at ReactCompositeComponentMixin.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactCompositeComponent.js:99:36)
at ReactPerf.measure.wrapper [as mountComponent] (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactPerf.js:27:23)
at Object.ReactReconciler.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactReconciler.js:11:37)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactMultiChild.js:75:46)
at ReactDOMComponent.Mixin._createContentMarkup (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactDOMComponent.js:146:34)
at ReactDOMComponent.Mixin.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactDOMComponent.js:95:76)
at Object.ReactReconciler.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactReconciler.js:11:37)
at ReactCompositeComponentMixin.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactCompositeComponent.js:99:36)
这似乎与 DevTools 有关。
这是我尝试使用它们的方式;
import React, { PropTypes, Component } from 'react'
import { Redirect, Router, Route } from 'react-router'
import { Provider } from 'react-redux'
import { createStore, combineReducers, compose, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import logger from './middleware/logger'
import persistenceStore from './persistence/store'
import { devTools } from 'redux-devtools'
import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react.js'
import App from './containers/App'
import * as storage from './persistence/storage'
import * as components from './components/index'
import * as reducers from './reducers/index'
import * as constants from './constants'
const __DEVTOOLS__ = true
const {
AccountsList,
Dashboard,
SideBar,
TitleBar,
Login
} = components
const initialState = {
application: {
token: storage.get('token'),
user: { permissions: [] }
}
}
let combinedCreateStore
const storeEnhancers = [persistenceStore]
if (__DEVTOOLS__) {
storeEnhancers.push(devTools())
}
combinedCreateStore = compose(...storeEnhancers)(createStore)
const finalCreateStore = applyMiddleware(thunk, logger)(combinedCreateStore)
const combinedReducer = combineReducers(reducers)
const store = finalCreateStore(combinedReducer, initialState)
function getRootChildren (history) {
const rootChildren = [
<Provider key='provider' store={store}>
{renderRoutes.bind(null, history)}
</Provider>
]
if (__DEVTOOLS__) {
rootChildren.push((
<DebugPanel key='debug-panel' top right bottom>
<DevTools store={store} monitor={LogMonitor}/>
</DebugPanel>
))
}
return rootChildren
}
export default class Root extends Component {
static propTypes = {
history: PropTypes.object.isRequired
}
render () {
const { history } = this.props
return (
<div>{getRootChildren(history)}</div>
)
}
}
function renderRoutes (history) {
return (
<Router history={history}>
<Route component={App}>
<Route path='/' component={Dashboard} />
<Route path='accounts' component={AccountsList} />
<Route path='login' component={Login} />
<Route path='logout' onEnter={logout} />
</Route>
</Router>
)
}
function requireAuth (nextState, redirectTo) {
const state = store.getState()
const isLoggedIn = Boolean(state.application.token)
if (!isLoggedIn) {
redirectTo('/login', {
nextPathname: nextState.location.pathname
})
}
}
function logout (nextState, redirectTo) {
store.dispatch({ type: constants.LOG_OUT })
redirectTo('/login')
}
这是我的 package.json
{
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "standard"
},
"author": "",
"jspm": {
"directories": {
"baseURL": "app"
},
"dependencies": {
"classnames": "npm:classnames@^2.1.3",
"history": "npm:history@^1.8.4",
"react": "npm:react@^0.13.3",
"react-pure-render": "npm:react-pure-render@^1.0.2",
"react-redux": "npm:react-redux@^2.1.1",
"react-router": "npm:react-router@1.0.0-beta4",
"redux": "npm:redux@^2.0.0",
"redux-devtools": "npm:redux-devtools@^2.1.0",
"redux-thunk": "npm:redux-thunk@^0.1.0"
},
"devDependencies": {
"babel": "npm:babel-core@^5.8.22",
"babel-runtime": "npm:babel-runtime@^5.8.20",
"core-js": "npm:core-js@^1.1.0"
}
},
"devDependencies": {
"browser-sync": "^2.9.1",
"foundation-apps": "^1.1.0",
"gulp": "^3.9.0",
"gulp-sass": "^2.0.4",
"redux": "^2.0.0",
"redux-devtools": "^2.0.0",
"rimraf": "^2.4.3",
"standard": "^5.2.1",
"vinyl": "^0.5.3"
}
}
如果我设置 __DEVTOOLS__ = false
我没有看到任何错误并且应用程序按预期呈现。
我的实现基于这个 webpack 示例,它工作得很好:
https://github.com/emmenko/redux-react-router-async-example
我做错了什么?
如 this issue 中所述,问题是由于广告拦截器阻止了对名为 pop.js
的内部文件的请求。关闭你的广告拦截器,你会没事的。
将 jspm / system.js 与 Babel 转译器一起使用时,我在控制台中看到以下错误
Uncaught (in promise) Error: XHR error loading http://localhost:3000/jspm_packages/npm/redux-devtools@2.1.0/lib/react/themes/pop.js
Error loading http://localhost:3000/jspm_packages/npm/redux-devtools@2.1.0/lib/react/themes/pop.js as "./pop" from http://localhost:3000/jspm_packages/npm/redux-devtools@2.1.0/lib/react/themes/index.js
at r (http://localhost:3000/jspm_packages/system.js:4:10975)
at XMLHttpRequest.o.onreadystatechange (http://localhost:3000/jspm_packages/system.js:4:11500)
如果我注释掉 react/themes/index.js
中的那一行,我(正如预期的那样)不会再看到该错误。
不过,我确实看到了这个;
Uncaught (in promise) Error: Cannot read property 'hasOwnProperty' of undefined
Error loading http://localhost:3000/index.js
at Object.checkAndWarnForMutatedProps (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactElementValidator.js:157:27)
at Object.ReactReconciler.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactReconciler.js:13:31)
at ReactCompositeComponentMixin.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactCompositeComponent.js:99:36)
at ReactPerf.measure.wrapper [as mountComponent] (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactPerf.js:27:23)
at Object.ReactReconciler.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactReconciler.js:11:37)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactMultiChild.js:75:46)
at ReactDOMComponent.Mixin._createContentMarkup (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactDOMComponent.js:146:34)
at ReactDOMComponent.Mixin.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactDOMComponent.js:95:76)
at Object.ReactReconciler.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactReconciler.js:11:37)
at ReactCompositeComponentMixin.mountComponent (http://localhost:3000/jspm_packages/npm/react@0.13.3/lib/ReactCompositeComponent.js:99:36)
这似乎与 DevTools 有关。
这是我尝试使用它们的方式;
import React, { PropTypes, Component } from 'react'
import { Redirect, Router, Route } from 'react-router'
import { Provider } from 'react-redux'
import { createStore, combineReducers, compose, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import logger from './middleware/logger'
import persistenceStore from './persistence/store'
import { devTools } from 'redux-devtools'
import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react.js'
import App from './containers/App'
import * as storage from './persistence/storage'
import * as components from './components/index'
import * as reducers from './reducers/index'
import * as constants from './constants'
const __DEVTOOLS__ = true
const {
AccountsList,
Dashboard,
SideBar,
TitleBar,
Login
} = components
const initialState = {
application: {
token: storage.get('token'),
user: { permissions: [] }
}
}
let combinedCreateStore
const storeEnhancers = [persistenceStore]
if (__DEVTOOLS__) {
storeEnhancers.push(devTools())
}
combinedCreateStore = compose(...storeEnhancers)(createStore)
const finalCreateStore = applyMiddleware(thunk, logger)(combinedCreateStore)
const combinedReducer = combineReducers(reducers)
const store = finalCreateStore(combinedReducer, initialState)
function getRootChildren (history) {
const rootChildren = [
<Provider key='provider' store={store}>
{renderRoutes.bind(null, history)}
</Provider>
]
if (__DEVTOOLS__) {
rootChildren.push((
<DebugPanel key='debug-panel' top right bottom>
<DevTools store={store} monitor={LogMonitor}/>
</DebugPanel>
))
}
return rootChildren
}
export default class Root extends Component {
static propTypes = {
history: PropTypes.object.isRequired
}
render () {
const { history } = this.props
return (
<div>{getRootChildren(history)}</div>
)
}
}
function renderRoutes (history) {
return (
<Router history={history}>
<Route component={App}>
<Route path='/' component={Dashboard} />
<Route path='accounts' component={AccountsList} />
<Route path='login' component={Login} />
<Route path='logout' onEnter={logout} />
</Route>
</Router>
)
}
function requireAuth (nextState, redirectTo) {
const state = store.getState()
const isLoggedIn = Boolean(state.application.token)
if (!isLoggedIn) {
redirectTo('/login', {
nextPathname: nextState.location.pathname
})
}
}
function logout (nextState, redirectTo) {
store.dispatch({ type: constants.LOG_OUT })
redirectTo('/login')
}
这是我的 package.json
{
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "standard"
},
"author": "",
"jspm": {
"directories": {
"baseURL": "app"
},
"dependencies": {
"classnames": "npm:classnames@^2.1.3",
"history": "npm:history@^1.8.4",
"react": "npm:react@^0.13.3",
"react-pure-render": "npm:react-pure-render@^1.0.2",
"react-redux": "npm:react-redux@^2.1.1",
"react-router": "npm:react-router@1.0.0-beta4",
"redux": "npm:redux@^2.0.0",
"redux-devtools": "npm:redux-devtools@^2.1.0",
"redux-thunk": "npm:redux-thunk@^0.1.0"
},
"devDependencies": {
"babel": "npm:babel-core@^5.8.22",
"babel-runtime": "npm:babel-runtime@^5.8.20",
"core-js": "npm:core-js@^1.1.0"
}
},
"devDependencies": {
"browser-sync": "^2.9.1",
"foundation-apps": "^1.1.0",
"gulp": "^3.9.0",
"gulp-sass": "^2.0.4",
"redux": "^2.0.0",
"redux-devtools": "^2.0.0",
"rimraf": "^2.4.3",
"standard": "^5.2.1",
"vinyl": "^0.5.3"
}
}
如果我设置 __DEVTOOLS__ = false
我没有看到任何错误并且应用程序按预期呈现。
我的实现基于这个 webpack 示例,它工作得很好: https://github.com/emmenko/redux-react-router-async-example
我做错了什么?
如 this issue 中所述,问题是由于广告拦截器阻止了对名为 pop.js
的内部文件的请求。关闭你的广告拦截器,你会没事的。