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. Iterators/Generators
  10. AsyncGenerators
  11. CustomElements/WebComponents

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 within the surrounding component. That is to say you do not need to bind your event handlers if you are not sending them as callbacks to other components.


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 supports EventListeners and multiple Arrays.


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

Implicit setState also compliments events, allowing us to construct components in the following functional way while maintaining the benefits of contained state.


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 host enviroment 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
	})
}