Differences Between Composi and React
Although Composi and React share many API features, there are substantial differences. The following tables show what they share and how they differ.
API
Composi | React |
---|---|
h | React.createElement |
mount | ReactDOM.hydrate |
render | ReactDOM.render |
Component | React.Component |
Component.render | React.Component.render |
Component.state | React.Component.state |
Component.setState | React.Component.setState |
Component.update | React.Component.forceUpdate |
Component.unmount | N/A |
Fragment | React.Fragment |
Composi uses mount
to render a functional component the first time. This returns a reference to the component tree. You can pass that reference to the render
function in order to update that functional component efficiently.
mount
is also used to hydrate server-side rendered DOM with functional components, similar to ReactDOM.hydrate
. Just pass a DOM reference for the structure to hydrate as the third argument to mount
:
// Hydrate H1 inside header tag:
mount(<Title message='Amazing Title'/> 'header', 'h1')
Use render
to update an already mounted functional component:
const title = mount(<Title message='Boring!'/>, 'header')
// Sometime later update the title.
// Pass in the 'title' variable from above:
render(<Title message='An Amazing Title!!!'/>, title)
Properties
Composi | React |
---|---|
class | className |
inline events | inline events (synthesized) |
onclick | onClick |
oninput | onUpdate |
for | htmlFor |
xlink-href or xlinkHref | xlinkHref |
innerHTML (string) | dangerouslySetInnerHTML (callback) |
style (accepts object or standard inline string value) | style (accepts object) |
Inline events are just inline events, same as they've always been since DOM Level 0. Composi uses standard HTML attributes. No need for camel case or non-standard terms. For SVG icons you can use xlink-href
. innerHTML
works as it normally does with DOM elements. It accepts a string as its value. No need for a complicated function like with React. style
can take a JavaScript object literal of key value pairs, or you can use a string as you normally would with HTML. React and friends only accept an object.
For inserting arbitrary markup into the DOM, Composi uses innerHTML
. React uses dangerouslySetInnerHTML
, which requires a callback.
function Title() {
return (
<h1>Original Content</h1>
)
}
const title = mount(<Title/>, 'header')
// Later update the title:
title = render(title, <Title innerHTML='The New Title!'/>, 'header')
Lifecycle Hooks for Class Components
Composi | React |
---|---|
componentWillMount | componentWillMount/UNSAFE_componentWillMount |
componentDidMount | componentDidMount |
componentWillUpdate | componentWillUpdate/UNSAFE_componentWillUpdate |
componentDidUpdate | componentDidUpdate |
componentWillUnmount | componentWillUnmount/UNSAFE_componentWillUnmount |
N/A | componentWillReceiveProps/UNSAFE_componentWillReceiveProps |
N/A | getDerivedStateFromProps |
componentShouldUpdate (attribute) | componentShouldUpdate (callback) |
componentShouldUpdate
is an attribute that accepts a boolean value. By default it is true. Setting this property to false will prevent it from updating, event when its state changes. After making state changes, you can flag the component to update again by setting this property to true. The next update will show the changes. In contrast, this is a function that meeds to return a boolean.
class Title extends Component {
render(data) {
return (
<h1>{data}</h1>
)
}
}
// Create instance.
// Because it has no state, it does not yet render.
const title = new Title({
state: 'A Great Title',
container: 'header'
})
title.componentShouldUpdate = false
// Sometime later you want to change the title.
// Because 'componentShouldUpdate' was set to false, nothing will happen.
title.setState('A Brand New Title!')
// To update the component, set 'componentShouldUpdate' to true,
// then run 'update' on the component instance:
title.componentShouldUpdate = true
title.update()
Lifecycle Events for Functional Components
Composi provides lifecycle hooks for functional components. These are used like inline events. React has n equivalent.
Composi | React |
---|---|
onmount | N/A |
onupdate | N/A |
onunmount | N/A |
onComponentDidMount
gets passed the root element of the functional component. componentDidUpdate
gets passed the old props, the new props and the root element of the component. onComponentWillUnmount
gets passed the parent element of the component.
// Use 'onComponentDidMount' to register event on component:
function List(props) {
return (
<div class='container-list' onComponentDidMount={(element)=> initEvent(element)}>
<ListForm />
<ul class='list-fruit'>
{props.items.map(item => <ListItem {...{item}}/>)}
</ul>
</div>
)
}
// Access the component element to register event:
function initEvent(element) {
element.addEventListener('click', callBack)
}
Codepen Example:
See the Pen Composi functional-components-4 by Robert Biggs (@rbiggs) on CodePen.
createRef/Ref
Composi | React |
---|---|
N/A (use this.element with componentDidMount to access DOM) | React.createRef |
N/A (same as above) | ref |
Composi does not have createRef
like React, and so it does not support the ref
property on elements. But you don't need it. Instead you can take advantage of a component's element
property in the componentDidUpdate
lifecycle hook to access elements in the DOM:
See the Pen Composi No Ref by Robert Biggs (@rbiggs) on CodePen.
Instantiation
Composi | React |
---|---|
mount (for functional components) | ReactDOM.hydrate/ReactDOM.render |
new - use to instatiate class component | React.DOM.render |
To render a functional component the first time, use mount
:
function Title({message}) {
return (
<nav>
<h1>{message}</h1>
</nav>
)
}
// Mount the custom tag in the header:
const title = mount(<Title message='A Great Title'/>, 'header')
To mount a class component, instantiate it with the new
keyword. If the class component has state, it will render to the DOM automatically when you instantiate it. If it is stateless, you'll need to run update
on the instance to render it.
Here we create a stateful component. By instantiating it witht he new
keyword, the component renders immediately:
See the Pen Composi Instantiation - 1 by Robert Biggs (@rbiggs) on CodePen.
Here we create a stateless component. When we instantiate it, we provide state. This causes the component to render immediately:
See the Pen Composi Instantiation - 2 by Robert Biggs (@rbiggs) on CodePen.
Here we create a stateless component. When we instantiate it, nothing happens. However, when we set state on the component instance with the setState
method, the component renders immediately:
See the Pen Composi Instantiation - 3 by Robert Biggs (@rbiggs) on CodePen.
Here we create a stateless component. It will never have state. When we instantiate it, nothing happens. We provide it data to render by passing the data to the update
method. This is therefore a "pure" component.
See the Pen Composi Instantiation - 4 by Robert Biggs (@rbiggs) on CodePen.