Comparison


If you're reading this page, you probably have used other frameworks to build applications, and you want to know what makes DIO different from React.

As a rule of thumb, if your team is already heavily invested in another framework/library/stack, it makes more sense to stick with it, unless your team agrees that there's a very strong reason to justify a costly rewrite.


API

Both React and DIO share a lot in common. If you already know React, then you already know almost all you need to build apps with DIO.

  1. They both use the same API's, lifecycle methods and key-based reconciliation heuristics.
  2. They both organize views with components.

Rendering

Rendering supports a vide variety of JavaScript Objects that can be rendered, these include.

  1. Elements
  2. Strings
  3. Numbers
  4. Null/Undefined
  5. Functions
  6. Fragments
  7. Portals
  8. Promises
  9. Generators

Statefull Functional Components

Functional components can maintain state, lifecycles and string refs like their class counter parts.


const User = (props, {name}, context) => {
	return h('h1', name)
}

User.getInitialState = (props) => {
	return {
		name: 'Earth'
	}
}

This means that the only difference between functional and class components is in how your write them.

Events

Events always maintain a this reference to the surrounding component.


class User {
	handleEvent(e, props, state, context) {
		return {
			value: 'Fox'
		}
	}
	render(props, {value}, context) {
		return h('input', {onInput: this.handleEvent, value: value})
	}
}

In additon events also support the EventListener interface.


class User {
	handleEvent(e, props, state, context) {
		return {
			value: 'Fox'
		}
	}
	render(props, {value}, context) {
		return h('input', {onInput: this, value: value})
	}
}

Implicit setState also compliments events, allowing us to construct components in the following way.


const User = (props, {value}, context) => {
	return h('input', {onInput: handleEvent, value: value})
}

const handleEvent = (e, props, state, context) => {
	return {
		value: 'Fox'
	}
}

Implicit setState

Implicit setState is a heuristic used to call setState without explicity calling setState. This can be used in events and any lifecycle method with the exception of shouldComponentUpdate and componentWillUnmount.


const User = (props, {name}, context) => {
	return h('h1', name)
}

User.componentDidMount = (node) => {
	return {
		name: 'Wind'
	}
}

async setState

This refers to the setState API supporting Promises as a value used to update state once the promise resolves.

This compliments implicit setState, allowing the following functional patterns to emerge.


const User = (props, {name}, context) => {
	return h('h1', name)
}

User.getInitialState = async (props) => {
	return {
		name: 'Earth'
	}
}

User.componentDidMount = async (node) => {
	return {
		name: 'Wind'
	}
}

Async getInitialState

getInitialState like other lifecycles methods supports implicit Promise setState with the addition that async getInitialState works on both the client and server when used with renderToNodeStream.


const User = (props, {name}, context) => {
	return h('h1', name)
}

User.getInitialState = async (props) => {
	return {
		name: 'Earth'
	}
}

Async componentWillUnmount

The componentWillUnmount lifecycle doesn't support an implicit setState but it does support async unmounting to make it easier to manage outro animations for components.

That is to say if you return a Promise from componentWillUnmount, the component will stay in a transient state in which in doesn't exist in the virtual tree but is kept alive in the native DOM untill the Promise has resolved.


const User = (props, {name}, context) => {
	return h('h1', name)
}

User.getInitialState = async (props) => {
	return {
		name: 'Earth'
	}
}

User.componentDidMount = async (node) => {
	return {
		name: 'Wind'
	}
}

User.componentWillUnmount = async (node) => {
	return new Promise((resolve) => {
		node.animate({...}).onfinish = resolve
	})
}