Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage with typescript? #17

Closed
xaviergonz opened this issue Feb 17, 2017 · 29 comments
Closed

Usage with typescript? #17

xaviergonz opened this issue Feb 17, 2017 · 29 comments

Comments

@xaviergonz
Copy link

xaviergonz commented Feb 17, 2017

Given this base code:

export class CounterStore {
  @observable counter: number = 0;
}

export class AppStore {
  @observable readonly counter: CounterStore = new CounterStore();
}

I tried:

const appStore: AppStore = new remotedev(AppStore)();
export default appStore;

But it gives:
Uncaught TypeError: Cannot call a class as a function

So then I tried decorating the AppStore class itself as:

@remotedev
export class AppStore {
  @observable readonly counter: CounterStore = new CounterStore();
}

const appStore: = new AppStore();
export default appStore;

And then it gives
Uncaught TypeError: Class constructor AppStore cannot be invoked without 'new' at new store (C:\VSProjects\SkirmishJs\server\node_modules\mobx-remotedev\lib\dev.js:48:67)

Is there a way to make it work using typescript classes?

PS: typescript types for the library would be cool too :)

@zalmoxisus
Copy link
Owner

That's a shame to confess, but I still didn't get to use TypeScript (just a bit of Flow). A pr to add types for the library would be much appreciated.

@Jonatthu
Copy link

yes we need this feature

@azukaar
Copy link

azukaar commented Mar 1, 2017

It's weird, on my side if I try


@remotedev({ global: true })
class AppState {
    @observable timer = 0;

    @action
    bumpTimer() {
        this.timer++;
    }
}

export default AppState;

....


const appState =  new AppState();

It doesnt trigger an error but simply doesnt let me debug at all

@zalmoxisus
Copy link
Owner

@azukaar do you have the extension installed?

@yann-stepienik-cko
Copy link

yann-stepienik-cko commented Mar 2, 2017

@zalmoxisus yeah yeah I do,, and it tells me "No store found. Make sure to follow the instructions.". Even AFTER actions are indeed triggered

@zalmoxisus
Copy link
Owner

@azukaar @yann-stepienik-cko see the notes about environment. By default it works only when process.env.NODE_ENV === 'development'.

If that's not the case, please share a simple repo I could run. I tried your snippet and it works as expected.

@azukaar
Copy link

azukaar commented Mar 5, 2017

@zalmoxisus I've been able to make it work by adding a NODE_ENV thanks !
I think everything work now.

@xaviergonz if you're still unable to use the plugin with TS feel free to chekcout my code !

Here is the repo : https://github.com/azukaar/react-typescript-mobx-webpack

@WearyMonkey
Copy link

FYI I reproduced this when TypeScript target language is es6, but not es5.

@zalmoxisus
Copy link
Owner

zalmoxisus commented Mar 23, 2017

@WearyMonkey seems like the class is not extended (since it's in commonjs/es5 from inside the lib). You can try to do it on your side like here. Where spy will be imported from mobx-remotedev/lib/spy.

You can also create a decorator like here.

@samhh
Copy link

samhh commented Aug 10, 2017

I'm experiencing this issue in a Babel setup including transform-class-properties if that's relevant.

import { observable, action } from 'mobx'
import remotedev from 'mobx-remotedev/lib/dev'

@remotedev({ name: 'example', global: true })
class ExampleStore {
	@observable example = ''

	@action setExample = text => {
		this.example = text
	}
}

export default new ExampleStore()

Mobx itself works fine, but upon adding that remotedev decorator I get Uncaught TypeError: Class constructor ExampleStore cannot be invoked without 'new'.

@baygeldin
Copy link

For what it's worth I just added a mobx-remotedev.d.ts file to local @types folder in the project root (i.e. not node_modules/@types) with the following content:

declare module 'mobx-remotedev' {
  export default function<T>(store: T): T
}

I also added the following lines to tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "*": ["@types/*"]
    }
  }
}

This is obviously not the full declaration, but it's enough in my case. And it also works with React Native debugger which is just awesome.

@BlackFenix2
Copy link
Collaborator

HI @zalmoxisus, i absolutely hate Redux but i love their devtool. I also love Mobx and hate their devtools.

to make matters complicated, i love Typescript but i also hate Babel. is there a way for me to enjoy this wonderful package without using babel at all?

@zalmoxisus
Copy link
Owner

@BlackFenix2 yes, we just need index.d.ts file in our package root with definitions, which typescript will pick by default when you import our package. If someone can submit a PR adding it I'd publish a new version to npm with it. Could add just export default function<T>(store: T): T as @baygeldin suggested, but not sure it will work for all cases (store can be a class or an object or probably other types which can be observable).

@BlackFenix2
Copy link
Collaborator

BlackFenix2 commented Feb 2, 2019

@zalmoxisus i made a PR adding index.d.ts. its minimal but it should work.

#37

@zalmoxisus
Copy link
Owner

Thanks @BlackFenix2! I published it as [email protected].

@BlackFenix2
Copy link
Collaborator

Thanks @BlackFenix2! I published it as [email protected].

NP, ill give it a try now!

i might make another PR to add more detailed Typescript definitions.

@BlackFenix2
Copy link
Collaborator

terribly sorry, but i should of declared export default function<T>(store: T, config:object): T
instead of export default function<T>(store: T): T,
i forgot about the config object passed in as a second argument. ill get another PR with the correct Type definition ready ☹️

@zalmoxisus
Copy link
Owner

NP, thanks for working on this @BlackFenix2!

@BlackFenix2
Copy link
Collaborator

i submitted another PR to address the index.d.ts bug #38

i also included a basic RemoteDevConfig object definition.

@zalmoxisus
Copy link
Owner

Thanks @BlackFenix2! It's published as 0.3.2.

@BlackFenix2
Copy link
Collaborator

I tried out the new version, the TypeDefinitions are there but i am still getting the error:
TypeError: Class constructor RootStore cannot be invoked without 'new'

this is my base code:

import remotedev from 'mobx-remotedev';

// import stores
import FruitStore from './fruitStore';
import RouteStore from './routeStore';
import ShowStore from './showStore';
import TodoStore from './todoStore';

class RootStore {
  TodoStore = new TodoStore();
  ShowStore = new ShowStore();
  FruitStore = new FruitStore();
  RouteStore = new RouteStore();
}

export default remotedev(RootStore, { global: true });

and this is where i add the stores to my provider:

import createBrowserHistory from 'history/createBrowserHistory';
import { Provider as MobxProvider } from 'mobx-react';
import { RouterStore, syncHistoryWithStore } from 'mobx-react-router';
import * as React from 'react';
import { Router } from 'react-router';
import RootStore from 'src/state/stores';
import Body from './Body';
import Footer from './Footer';
import Header from './Header';

// set up Mobx Routing Store
const browserHistory = createBrowserHistory();
const RoutingStore = new RouterStore();
const rootStore = new RootStore();
const history = syncHistoryWithStore(browserHistory, RoutingStore);

class App extends React.Component {
  render() {
    return (
      <MobxProvider {...rootStore} routing={RoutingStore}>
        <Router history={history}>
          <AppLayout />
        </Router>
      </MobxProvider>
    );
  }
}

const AppLayout = () => (
  <React.Fragment>
    <Header />
    <Body />
    <Footer />
  </React.Fragment>
);

export default App;

and this is the line that throws an error for me in lib/dev.js:
var _this = _possibleConstructorReturn(this, _store2.call.apply(_store2, [this].concat(args)));

i may be a little stumped at this point. im going to try and use the repo recommend by @azukaar
https://github.com/azukaar/react-typescript-mobx-webpack

@BlackFenix2
Copy link
Collaborator

BlackFenix2 commented Feb 3, 2019

https://github.com/azukaar/react-typescript-mobx-webpack
so far all i found out is that i need the babel preset "presets": ["es2015"] to get the Error to disappear and enable the devtools.

now we got to figure out a way to get this working with zero babel.

@zalmoxisus
Copy link
Owner

@BlackFenix2 does TS use that definition we added? Maybe it should be in lib folder?

@BlackFenix2
Copy link
Collaborator

@zalmoxisus the default function is getting the type definitons below.

(alias) remotedev<typeof TodoStore>(store: typeof TodoStore, config?: RemoteDevConfig): typeof TodoStore (+1 overload) import remotedev

export const test = remotedev(TodoStore, { onlyActions: true });

i know the error happens at line 50 in dev.js when the call method is invoked

for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }

         =>var _this = _possibleConstructorReturn(this, _store2.call.apply(_store2, [this].concat(args)));

        (0, _spy2.default)(_this, config);
        return _this;

since the lib directory is compiled we might be able to use Typescript to compile the files rather than Babel, like in this fork:
https://github.com/hlhr202/mobx-remotedev

it is behind your main branch. but i can attempt to add this to my fork and test the package locally. ill investigate.

@BlackFenix2
Copy link
Collaborator

Almost forgot to mention, if i use this .babelrc config and tsconfig.json remotedev works perfectly for me

.babelrc
{ "presets": ["@babel/env", "@babel/typescript"], "plugins": [ "@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-runtime" ] }

tsconfig.json

{
  "compilerOptions": {
    // compile JSX syntax to JS
    "jsx": "react",

    // use latest ES version including proposed features
    "module": "esnext",
    "target": "esnext",

    // targets node
    "moduleResolution": "node",

    // force case-sensitive imports to avoid compile-time errors
    "forceConsistentCasingInFileNames": true,

    // allows default import of modules without default exports, shorthand for import * as item from 'module'
    "esModuleInterop": true,

    //Allow decorators
    "experimentalDecorators": true,

    //needed for mmlpx
    "emitDecoratorMetadata": true,

    //remove unneeded comments
    "removeComments": true,

    // ALIAS  src path
    "baseUrl": "./",
    "paths": {
      "src/*": ["src/*"]
    }
  },

  //testing support for mobx-remotedev package
  "awesomeTypescriptLoaderOptions": {
    "useBabel": true,
    //add Babel 7
    "babelCore": "@babel/core"
  }
}

i have it all working on my github repo https://github.com/BlackFenix2/Portfolio

the live site is react.erniefrancisiv.com/todo .redux devtools wont work here since production, but feel free to fork my repo and check for yourself.

@BlackFenix2
Copy link
Collaborator

All i figued out is that dev.js bugs out when i do not transpose my classes to fuctions with Babel.

line:

 console.log('Class or fuction:', _getPrototypeOf(store));
          _this = _possibleConstructorReturn(
            this,
            (_getPrototypeOf2 = _getPrototypeOf(store)).call.apply(
              _getPrototypeOf2,
              [this].concat(args)
            )
          );

with babel 7:

Class or fuction: ƒ TodoStore() {
    (0, _classCallCheck2.default)(this, TodoStore);
    this.todoList = [];
    this.testState = 'test';
  }

without babel:

Class or fuction: class TodoStore {
  constructor() {
      this.todoList = [];
      this.testState = 'test';
  }
get completedTasks() {
      return this.todoList.filter(todo => todo.isComplete).length… 

@BlackFenix2
Copy link
Collaborator

this PR #40 should fix the typescript issues.

@zalmoxisus
Copy link
Owner

zalmoxisus commented Feb 5, 2019

Thanks for fixing it @BlackFenix2! I also added you as a collaborator for this repo.

@alex-shamshurin
Copy link

Please update docs how to use it with typescript and how to export

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants