marty.js v0.10 by James Hollingworth

Today I'm pleased to announce Marty v0.10! So whats new?

marty-native

To complement React Natives arrival we now have marty-native. Internally marty and marty-native are actually the same code, the only difference being we need to require in react-native instead of react. This opens up some interesting code-sharing abilities we will discuss soon. You can check out our native chat example to see how to use Marty with React Native.

We've also updated Marty Developer Tools to allow you to debug native applications (as well as any app outside of Chrome, e.g. electron). See our guide for more details.

No more singletons

In previous versions of Marty everything was a singleton. This made it very simple to write your app, you just require in whatever you want and start using it. Unfortunately in exchange for simplicity we made some very important things like isomorphism and testing much harder. We introduced some changes in v0.9 (e.g. for) which helped improve the situation but never truly resolved it and so in v0.10 we decided to solve it once and for all.

In v0.10 there are no more singletons. Functions like Marty.createStore will now return a type rather than an instance, Marty.register is no longer needed and there is no global dispatcher. Instead we introduce a new Application type which is responsible for knowing about everything about your application.

var Marty = require('marty');
var ApplicationContainer = Marty.ApplicationContainer;

var ExampleApp = Marty.createApplication(function () {
    this.register({
        user: {
            store: require('./stores/userStore'),
            queries: require('./queries/userQueries'),
            actionCreators: require('./actions/userActionCreators'),
        }
    });
});

var app = new ExampleApp();

app.user.store.getUser(1);
app.dispatcher.register(console.log.bind(console));

React.render((
    <ApplicationContainer app={app}>
        <User id={123} />
    </ApplicationContainer>
), document.body);
var {
    Application,
    ApplicationContainer
}  = require('marty');

// application.js
class ExampleApp extends Application {
    constructor(options) {
        super(options);

        this.register({
            user: {
                store: require('./stores/userStore'),
                queries: require('./queries/userQueries'),
                actionCreators: require('./actions/userActionCreators'),
            }
        });
    }
}

var app = new ExampleApp();

app.user.store.getUser(1);
app.dispatcher.register(console.log.bind(console));

React.render((
    <ApplicationContainer app={app}>
        <User id={123} />
    </ApplicationContainer>
), document.body);

Applications give you more fine grained control over how you build your application, allowing you to do things like run multiple independent applications on a single page.

Testing your application becomes much simpler now that you can test components in isolation. We have a new set of test utils that make testing Marty applications much easier. To accompany these utils we have a some examples about how to test the various bits of a Marty application.

This will be a fairly large change for those upgrading from v0.9. Our upgrade guide should cover everything you need to know. We've also updated our chat example. If you need any further help you can chat to us on gitter.im/martyjs/marty

ES7 features

While ES7 is still a while away, thanks to babel we can start playing with it now. We've added experimental support for class properties and decorators. To enable make sure stage 0 is enabled in your babel options.

let { handles } = require('marty');

class UserStore extends Marty.Store {
    // Equivalent to getInitialState()
    state = { };

    @handles(UserConstants.RECEIVE_USER)
    addUser(user) {
        ...
    }
}

Marty's gone on a diet

We've shave 2.5KB off Marty's gzipped file size (25KB vs 27.5KB). This was mostly down to us removing a lot of old, unused features which we're making Marty bloated and complicated to understand.

Changelog

For those currently using Marty v0.9, we've written a guide for upgrading to v0.10.

 New features

Deprecations

  • Due to API incompatibility issues parseJSON will be removed by default in future versions. Instead you should call this.json() from within your state source.

Removed

  • Marty.register() is no longer needed, just return the type
  • You will no longer be able to pass in a store or an object hash of stores into Marty.createStateMixin
  • Rollbacks have been removed entirely
  • Store handler values can only be either a string or an array of strings. You cannot do complex object queries any more.
  • Marty.registry is no longer supported. Use applications instead.
  • Marty.createContext() is no longer supported. Use applications instead.
  • Marty.renderToString() is no longer supported. Use Application#renderToString() instead
  • Store#rollback() is no longer supported. You should instead dispatch an error action.
  • .for(this) has been removed. Use applications instead.
  • You no longer to specify id's in the type. Instead define the Id on the Application#register()
  • require('marty').Dispatcher is no longer supported. Create an application and access the dispatcher.
  • require('marty/http/hooks') is no longer supported. Use require('marty').hooks instead
  • require('marty/environment') is no longer supported. Use require('marty').environment
  • require('marty/fetch') is no longer supported. Use require('marty').fetch
  • require('marty/when') is no longer supported. Use require('marty').when
  • require('marty/autoDispatch') is no longer supported. Use require('marty').autoDispatch
  • require('marty').Diagnostics is no longer supported. Use require('marty').diagnostics