Upgrading from Marty 0.9 to 0.10

If you've got any questions about upgrading you can ask the team in Marty's Gitter chatroom.

Singleton to Application

Firstly, if you're using ES6 you will need to remove all references to Marty.register(...) and just return the original type.

// Instead of
export default Marty.register(UserStore);

// You just export the type
export default UserStore;
Next you need to create a new Application instance and tell it about all of your types. If you're using webpack or browserify this process is significantly easier if you implement automatic registration.
var Application = Marty.createApplication(function () {
    this.register('userStore', require('./stores/userStore'));
    ...
});

module.exports = Application;
class Application extends Marty.Application {
    constructor(options) {
        super(options);
        this.register('userStore', require('./stores/userStore'));
        ...
    }
}

export default Application;

Next, when calling React.render you must wrap the element you are about to render with an ApplicationContainer, passing an instance of your application in via the props.

var app = new Application();
var { ApplicationContainer }  = require('marty');

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

Now that we're returning types instead of instances we need to update all references within our application. This largely means that, instead of require'ing your dependency, you must instead call this.app.{dependencyId}. e.g.

// Instead of
var UserAPI = require('../sources/userAPI');

class UserActions extends Marty.ActionCreators {
    deleteUser(id) {
        UserAPI.for(this).deleteUser(id);
    }
}

// Assuming you had registered UserAPI with the id 'userAPI'
class UserActions extends Marty.ActionCreators {
    deleteUser(id) {
        this.app.userAPI.deleteUser(id);
    }
}

This is largely the same from with React components. The only requirement is that the component is either wrapped in a container or is using the state mixin. There are times when neither are appropriate so we've introduced the app mixin which simply injects app into your component.

class User extends React.Component {
    saveUser() {
        this.app.userActionCreators.saveUser(this.props.id);
    }
}

export default Marty.createContainer(User);

For the listenTo property in containers and state mixins you need to replace type references with their dependency Id's. The listenTo behavior is identical otherwise.

export default Marty.createContainer(User, {
    // instead of
    listenTo: [
        UserStore,
        FriendsStore
    ],

    // Use strings
    listenTo: [
        'userStore',
        'friends.store' // To access app.friends.store
    ],

    fetch {
        user() {
            return this.app.userStore.getUser(123);
        }
    }
});

To update your tests, we recommend you look at our test examples and test utils.

Isomorphism

Contexts have been completely removed and most functions that were previously on Marty, e.g. Marty.replaceState, Marty.clearState, Marty.dehydrate and Marty.rehydrate have been moved to to the application.

// Instead of
var context = Marty.createContext();

Marty.replaceState({ ... }, context);
Marty.clearState(context);
Marty.dehyrdate(context);
Marty.rehydrate({ ... }, context);

// You do
var app = new Application();

app.replaceState({ ... });
app.clearState();
app.dehyrdate();
app.rehydrate({ ... });

Marty.renderToString has also been moved to the application and has simpler signature.

// Instead of
var context = Marty.createContext();
var options = {
  type: Foo,
  timeout: 2000,
  context: context,
  props: { bar: 'baz' }
};

Marty.renderToString(options).then(res => {
  console.log('Rendered html', res.html);
  console.log('Diagnostics', res.diagnostics);
});

// You do
var app = new Application();

app.renderToString(<Foo bar='baz' />, { timeout: 2000 }).then(res => {
  // We've had to split the html body and html state variables out to resolve https://github.com/martyjs/marty/issues/288.
  console.log('Rendered html body', res.htmlBody);
  console.log('Rendered html state', res.htmlState);
  console.log('Diagnostics', res.diagnostics);
});

parseJSON

The HttpStateSource internally uses fetch to make HTTP calls for you. If the response contains JSON you need to call res.json() to get the actual JSON. We thought we'd be helpful and do this for you automatically, assigning the JSON to res.body. Unfortunately we did this before we knew fetch was also going to use the body property for other purposes which has caused issues. We therefore need to depreciate this feature. For v0.10 you will get warnings and in v0.11 we will turn feature off by default.

To get rid of the warnings you first need to remove the HTTP hook

require('marty').HttpStateSource.removeHook('parseJSON');

Next you will need to update all references to res.body. We recommend putting all of this logic in your HTTP state source

class UserAPI extends Marty.HttpStateSource {
    getUser(id) {
        return this.get(`/users/${id}`).then(res => {
            if (res.ok) {
                return res.json();
            }

            throw new Error('Failed to get user');
        });
    }
}

State mixin's

We warned when we released v0.9 we would be depreciating the state mixin. We've decided to keep them around for v0.10 however we've removed the ability to create a state mixin by passing in a store or by passing in an object hash of stores.

// No longer possible
Marty.createStateMixin(UserStore)
Marty.createStateMixin({
    users: UserStore,
    friends: FriendsStore
});

Rollbacks

Rollbacks are no longer supported. We recommend you look at our suggested approach to handling errors.

Other Depreciations

  • You no longer need to declare Id's or displayName's on the type. An instances Id will be populated from from Application#register(id, type).
  • Marty.registry no longer exists. If you want to get all instances of a given type you can call Application#getAll(type)
  • 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