In the process of integrating ESLint to a MobX with decorators React project, I run into the problem of the stores being undefined.
I have read a lot of the posts regarding how to use decorators with mobx and there's a definite, reported way to make it work, but at the same time there's a sentiment in the air to just not use them and instead use the wrapper functions the decorators replace. I would not like to lose the readability and ease of use in way of a solution, but at this moment I'm not sure what else I can try to have this working.
At this moment I have two separate git branches in my project and can provide examples of the working build with decorators, as mentioned above the problem arises when adding linting tools
Code samples in question below:
App.jsx
import React, { Component } from 'react';
import { Route, withRouter } from 'react-router-dom';
import { inject, observer } from 'mobx-react';
import LazyRoute from 'lazy-route';
import styles from './styles/app.css';
@withRouter
@inject('store')
@observer
export default class App extends Component {
constructor(props) {
super(props);
this.store = this.props.store;
}
componentDidMount() {
//here's where the error is triggered, authenticate is a function in the store but it throws undefined
this.store.appState.authenticate();
}
render() {
return (
<div className={`container-fluid ${styles.wrapper}`}>
<Route exact path="/" render={props => <LazyRoute {...props} component={import('./Home')} />} />
<Route exact path="/profile" render={props => <LazyRoute {...props} component={import('./Profile')} />} />
<Route exact path="/balance" render={props => <LazyRoute {...props} component={import('./Balance')} />} />
<Route render={props => <LazyRoute {...props} component={import('./Home')} />} />
</div>
);
}
}
.babelrc
{ "presets": ["react", "es2015", "stage-1"], "plugins": ["transform-decorators-legacy"] }
dependencies:
"devDependencies": {
"babel": "^6.5.2",
"babel-core": "^6.18.0",
"babel-loader": "^6.2.7",
"babel-plugin-transform-async-to-generator": "^6.16.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-1": "^6.16.0",
"css-loader": "^0.25.0",
"extract-text-webpack-plugin": "^2.0.0-beta.4",
"html-webpack-plugin": "^2.22.0",
"image-webpack-loader": "^2.0.0",
"node-sass": "^3.10.1",
"postcss-loader": "^0.13.0",
"react-hot-loader": "next",
"resolve-url-loader": "^1.6.0",
"rimraf": "^2.5.4",
"sass-loader": "^4.0.2",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^2.4.1",
"webpack-dev-server": "^2.4.5"
},
"dependencies": {
"axios": "^0.15.0",
"babel-eslint": "^8.0.0",
"babel-preset-env": "^1.6.0",
"bootstrap": "^3.3.7",
"create-react-class": "^15.6.0",
"eslint": "^3.19.0 || ^4.3.0",
"eslint-config-airbnb": "^15.1.0",
"eslint-config-prettier": "^2.5.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jsx-a11y": "^5.1.1",
"eslint-plugin-prettier": "^2.3.0",
"eslint-plugin-react": "^7.1.0",
"faker": "^3.1.0",
"http-server": "^0.10.0",
"jquery": "^3.2.1",
"lazy-route": "^1.0.7",
"mobx": "^2.5.2",
"mobx-react": "4.0.0",
"mobx-react-devtools": "^4.2.6",
"moment": "^2.18.1",
"package": "^1.0.1",
"react": "^15.6.1",
"react-bootstrap": "latest",
"react-bootstrap-date-picker": "^5.1.0",
"react-dom": "^15.6.1",
"react-loader": "^2.4.2",
"react-router-dom": "latest",
"react-stripe-elements": "^0.0.8",
"rfx-core": "^1.5.3",
"transform-runtime": "^0.0.0",
"whatwg-fetch": "^1.0.0"
}
webpack.config.js:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: ['webpack-dev-server/client?http://0.0.0.0:3000', 'babel-polyfill', 'whatwg-fetch', './src/index.jsx'],
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
port: 8000,
host: 'localhost',
publicPath: '/',
historyApiFallback: true,
disableHostCheck: true,
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: 'app.[hash].js',
},
devtool: 'eval',
module: {
rules: [
{
test: /\.js$|jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.scss|css$/,
use: [
'style-loader',
'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
'postcss-loader',
'resolve-url-loader',
'sass-loader?sourceMap',
],
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
'file-loader?hash=sha512&digest=hex&name=[hash].[ext]',
{
loader: 'image-webpack-loader',
options: {
progressive: true,
optimizationLevel: 7,
interlaced: false,
pngquant: {
quality: '65-90',
speed: 4,
},
},
},
],
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: 'url-loader?limit=10000&mimetype=application/font-woff',
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: 'file-loader',
},
{
enforce: 'pre',
test: /\.jsx?$/,
loader: 'eslint-loader',
exclude: /node_modules/,
},
],
},
plugins: [
new webpack.NamedModulesPlugin(),
new HtmlWebpackPlugin({ hash: false, template: './index.hbs' }),
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /nb/),
],
};
Full console error message:
Uncaught TypeError: Cannot read property 'authenticate' of undefined
at App.componentDidMount (webpack:///./src/components/App.jsx?:54:26)
at App.target.(anonymous function) (webpack:///./~/mobx-react/index.js?:262:13)
at eval (webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:264:25)
at measureLifeCyclePerf (webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:75:12)
at eval (webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:263:11)
at CallbackQueue.notifyAll (webpack:///./~/react-dom/lib/CallbackQueue.js?:76:22)
at ReactReconcileTransaction.close (webpack:///./~/react-dom/lib/ReactReconcileTransaction.js?:80:26)
at ReactReconcileTransaction.closeAll (webpack:///./~/react-dom/lib/Transaction.js?:209:25)
at ReactReconcileTransaction.perform (webpack:///./~/react-dom/lib/Transaction.js?:156:16)
at batchedMountComponentIntoNode (webpack:///./~/react-dom/lib/ReactMount.js?:126:15)
I faced with that problem. That may help you:
1) Create a file in a root of project
jsconfig.json
containing following:2) You've already install
"babel-plugin-transform-class-properties"
, but maybe didn't use it. Try add'transform-class-properties'
to.babelrc
in plugins section right after'transform-decorators-legacy'
, in my case it helped me. Your plugins in.babelrc
should looks like: