Skip to content

v4.0.0

Compare
Choose a tag to compare
@mikaelbr mikaelbr released this 26 Oct 19:33
· 74 commits to master since this release

React 0.14.0 introduced some very nice features such as stateless components, and we saw that it hit very close the the usage as we've seen in Omniscient.js for the last year. With this change we made some simplifications to our components to be even more similar to vanilla React. Now you can use Omniscient.js as you would with vanilla React, just with added optimizations. Much like memoization for normal functions.

There are still some features only available through Omniscient.js components, though. Such as syntactic sugar for component keys, string-defined display names, easier access to immutable data or cursors (wrapping/unwrapping as single argument), and the ability to add life cycle methods if that's something you need.

Deletions

  1. There is no longer a magic statics property. Instead this is made explicit through a overridable option on the provided shouldComponentUpdate called isIgnorable. This function can be used to signal what property on the props that should be ignored. Nothing is ignored by default. You don't have to use isIgnorable manually, but you can use the ignore component provided as syntactic sugar in a helper library called omnipotent. See an example of this in the migration steps below.
  2. As there is no longer a default statics property, statics are no longer passed as second props argument to the function. This means you only get props as a single parameter to your stateless components (Cursors/Immutable structures are still wrapped/unwrapped). See examples in migration steps below.
  3. Now only supports React 0.14.0.
  4. No more .JSX extension. This was a workaround to get interoperability with JSX and non-JSX code. With React 0.14, this is no longer needed!
  5. No more need for own React Native package, as React and ReactDOM is separate packages as of React 0.14. This change removes ability and need of doing require('omniscient/native').

Additions

  1. Adds support for React Class level decorators. See relevant discussion and prompted need in issue #117.
    Example usage with decorator:
    js var decoratedComponent = component.withDefaults({ classDecorator: compose(Radium, function (Component) { var DecoratedComponent = doSomething(Component); return DecoratedComponent; }) }); * var Component = decoratedComponent(function (props) { // ... some implementation });

Internal Changes

  1. Now only builds on node 4.0.0 due to the latest jsdom.

Migration Steps

There are three things you need to change to get it working in the latest version. If you haven't used statics, there is nothing to change. The example before and after code below contains all the information you need to migrate.

Before

var MyComponent = component(function (props, statics) {
  var onClick = statics.clickHandler;
  return DOM.button({ onClick }, 'Click me!');
});

var App = component(function (props) {
  return MyComponent({
    text: 'Click me!'
  }, {
    // statics
    clickHandler: function () {
      console.log('Clicked the button!');
    }
  })
});

After

var shouldUpdate = require('omniscient/shouldupdate').withDefaults({
  isIgnorable: function (value, key) {
    // ignore properties with key `statics`
    return key === 'statics';
  }
});

var StaticsIgnoredComponent = component({
  shouldComponentUpdate: shouldUpdate
}, function (props) {
  var onClick = props.statics.clickHandler;
  return DOM.button({ onClick }, 'Click me!');
});

var App = component(function (props) {
  return StaticsIgnoredComponent({
    text: 'Click me!'
    statics: {
      clickHandler: function () {
        console.log('Clicked the button!');
      }
    }
  })
});

Or using the omnipotent helper:

var ignore = require('omnipotent/decorator/ignore');

var MyComponent = component(function (props) {
  var onClick = props.statics.clickHandler;
  return DOM.button({ onClick }, 'Click me!');
});

// Create a new component that has statics ignored
var StaticsIgnoredComponent = ignore('statics', MyComponent);

var App = component(function (props) {
  return StaticsIgnoredComponent({
    text: 'Click me!'
    statics: {
      clickHandler: function () {
        console.log('Clicked the button!');
      }
    }
  })
});

Migration Steps JSX removal

.jsx has been removed, but the migration is real simple. Remove all instances of .jsx and component.withDefaults({ jsx: true }) from your codebase.

Before

var MyComponent = component((props) => (
  <h1>Hello {props.text}</h1>
)).jsx; // note the `.jsx`

var App = component(() => (
  <div>
    <MyComponent text="Hello!" />
  </div>
)).jsx;

After

var MyComponent = component((props) => (
  <h1>Hello {props.text}</h1>
));

var App = component(() => (
  <div>
    <MyComponent text="Hello!" />
  </div>
));

As an added bonus you now have complete interoperability between jsx and non-jsx:

var MyComponent = component((props) => (
  <h1>Hello {props.text}</h1>
));

var App = component(() => (
  React.DOM.div({},
    MyComponent({ text: 'Hello!' })
  )
));