Inferno

Build Status Coverage Status MIT NPM npm downloads Discord gzip size Backers on Open Collective Sponsors on Open Collective

Inferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server.

Description

The main objective of the InfernoJS project is to provide the fastest possible runtime performance for web applications. Inferno excels at rendering real time data views or large DOM trees.

The performance is achieved through multiple optimizations, for example:

  • Inferno's own JSX compilers creates monomorphic createVNode calls, instead of createElement calls. Optimizing runtime performance of the application.
  • Inferno's diff process uses bitwise flags to memoize the shape of objects
  • Child nodes are normalized only when needed
  • Special JSX flags can be used during compile time to optimize runtime performance at application level
  • Many micro optimizations

Features

  • Component driven + one-way data flow architecture
  • React-like API, concepts and component lifecycle events
  • Partial synthetic event system, normalizing events for better cross browser support
  • Inferno's linkEvent feature removes the need to use arrow functions or binding event callbacks
  • Isomorphic rendering on both client and server with inferno-server
  • Unlike React and Preact, Inferno has lifecycle events on functional components
  • Unlike Preact and other React-like libraries, Inferno has controlled components for input/select/textarea elements
  • Components can be rendered outside their current html hierarchy using createPortal - API
  • Support for older browsers without any polyfills
  • defaultHooks for Functional components, this way re-defining lifecycle events per usage can be avoided
  • Inferno supports setting styles using string <div style="background-color: red"></div> or using object literal syntax <div style={{"background-color": "red"}}></div>. For camelCase syntax support see inferno-compat.
  • Fragments (v6)
  • createRef and forwardRef APIs (v6)
  • componentDidAppear, componentWillDisappear and componentWillMove (v8) - class and function component callbacks to ease animation work, see inferno-animation package

Runtime requirements

Inferno v9 requires following features to be present in the executing runtime:

  • Promise
  • String.prototype.includes()
  • String.prototype.startsWith()
  • Array.prototype.includes()
  • Object.spread()
  • for ... of

Browser support

Since version 4 we have started running our test suite without any polyfills. Inferno is now part of Saucelabs open source program and we use their service for executing the tests.

InfernoJS is actively tested with browsers listed below, however it may run well on older browsers as well. This is due to limited support of browser versions in recent testing frameworks. https://github.com/jasmine/jasmine/blob/main/release_notes/5.0.0.md

Browser Test Status

Migration guides

Benchmarks

Live examples at https://infernojs.github.io/inferno

Code Example

Let's start with some code. As you can see, Inferno intentionally keeps the same design ideas as React regarding components: one-way data flow and separation of concerns.

In these examples, JSX is used via the Inferno JSX Babel Plugin to provide a simple way to express Inferno virtual DOM. You do not need to use JSX, it's completely optional, you can use hyperscript or createElement (like React does). Keep in mind that compile time optimizations are available only for JSX.

import { render } from 'inferno';

const message = "Hello world";

render(
  <MyComponent message={ message } />,
  document.getElementById("app")
);

Furthermore, Inferno also uses ES6 components like React:

import { render, Component } from 'inferno';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    };
  }
  render() {
    return (
      <div>
        <h1>Header!</h1>
        <span>Counter is at: { this.state.counter }</span>
      </div>
    );
  }
}

render(
  <MyComponent />,
  document.getElementById("app")
);

Because performance is an important aspect of this library, we want to show you how to optimize your application even further. In the example below we optimize diffing process by using JSX $HasVNodeChildren and $HasTextChildren to predefine children shape compile time. In the MyComponent render method there is a div that contains JSX expression node as its content. Due to dynamic nature of Javascript that variable node could be anything and Inferno needs to go through the normalization process to make sure there are no nested arrays or other invalid data. Inferno offers a feature called ChildFlags for application developers to pre-define the shape of vNode's child node. In this example case it is using $HasVNodeChildren to tell the JSX compiler, that this vNode contains only single element or component vNode. Now inferno will not go into the normalization process runtime, but trusts the developer decision about the shape of the object and correctness of data. If this contract is not kept and node variable contains invalid value for the pre-defined shape (fe. null), then application would crash runtime. There is also span-element in the same render method, which content is set dynamically through _getText() method. There $HasTextChildren child-flag fits nicely, because the content of that given "span" is never anything else than text. All the available child flags are documented here.

import { createTextVNode, render, Component } from 'inferno';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    };
  }

  _getText() {
     return 'Hello!';
  }
  
  render() {
    const node = this.state.counter > 0 ? <div>0</div> : <span $HasTextChildren>{this._getText()}</span>;
      
    return (
      <div>
        <h1>Header!</h1>
        <div $HasVNodeChildren>{node}</div>
      </div>
    );
  }
}

render(
  <MyComponent />,
  document.getElementById("app")
);

Tear down

To tear down inferno application you need to render null on root element. Rendering null will trigger unmount lifecycle hooks for whole vDOM tree and remove global event listeners. It is important to unmount unused vNode trees to free browser memory.

import { createTextVNode, render, Component } from 'inferno';

const rootElement = document.getElementById("app");

// Start the application
render(
  <ExampleComponent/>,
  rootElement
);

// Tear down
render(
  null,
  rootElement
);

More Examples

If you have built something using Inferno you can add them here:

Getting Started

The easiest way to get started with Inferno is by using Create Inferno App.

Alternatively, you can try any of the following:

Core package:

npm install --save inferno

Addons:

# server-side rendering
npm install --save inferno-server
# routing
npm install --save inferno-router

Pre-bundled files for browser consumption can be found on our cdnjs:

Or on jsDelivr:

https://cdn.jsdelivr.net/npm/inferno@latest/dist/inferno.min.js

Or on unpkg.com:

https://unpkg.com/inferno@latest/dist/inferno.min.js

Creating Virtual DOM

JSX:

npm install --save-dev babel-plugin-inferno

Hyperscript:

npm install --save inferno-hyperscript

createElement:

npm install --save inferno-create-element

Compatibility with existing React apps

npm install --save-dev inferno-compat

Note: Make sure you read more about inferno-compat before using it.

Third-party state libraries

Inferno now has bindings available for some of the major state management libraries out there:

JSX

Inferno has its own JSX Babel plugin.

Differences from React

  • Inferno doesn't have a fully synthetic event system like React does. Inferno has a partially synthetic event system, instead opting to only delegate certain events (such as onClick).
  • Inferno doesn't support React Native. Inferno was only designed for the browser/server with the DOM in mind.
  • Inferno doesn't support legacy string refs, use createRef or callback ref API
  • Inferno provides lifecycle events on functional components. This is a major win for people who prefer lightweight components rather than ES2015 classes.

Differences from Preact

  • Inferno has a partial synthetic event system, resulting in better performance via delegation of certain events.
  • Inferno is much faster than Preact in rendering, updating and removing elements from the DOM. Inferno diffs against virtual DOM, rather than the real DOM (except when loading from server-side rendered content), which means it can make drastic improvements. Unfortunately, diffing against the real DOM has a 30-40% overhead cost in operations.
  • Inferno fully supports controlled components for input/select/textarea elements. This prevents lots of edgecases where the virtual DOM is not the source of truth (it should always be). Preact pushes the source of truth to the DOM itself.
  • Inferno provides lifecycle events on functional components. This is a major win for people who prefer lightweight components rather than ES2015 classes.

Event System

Like React, Inferno also uses a light-weight synthetic event system in certain places (although both event systems differ massively). Inferno's event system provides highly efficient delegation and an event helper called linkEvent.

One major difference between Inferno and React is that Inferno does not rename events or change how they work by default. Inferno only specifies that events should be camel cased, rather than lower case. Lower case events will bypass Inferno's event system in favour of using the native event system supplied by the browser. For example, when detecting changes on an <input> element, in React you'd use onChange, with Inferno you'd use onInput instead (the native DOM event is oninput).

Available synthetic events are:

  • onClick
  • onDblClick
  • onFocusIn
  • onFocusOut
  • onKeyDown
  • onKeyPress
  • onKeyUp
  • onMouseDown
  • onMouseMove
  • onMouseUp
  • onTouchEnd
  • onTouchMove
  • onTouchStart

linkEvent (package: inferno)

linkEvent() is a helper function that allows attachment of props/state/context or other data to events without needing to bind() them or use arrow functions/closures. This is extremely useful when dealing with events in functional components. Below is an example:

import { linkEvent } from 'inferno';

function handleClick(props, event) {
  props.validateValue(event.target.value);
}

function MyComponent(props) {
  return <div><input type="text" onClick={ linkEvent(props, handleClick) } /><div>;
}

This is an example of using it with ES2015 classes:

import { linkEvent, Component } from 'inferno';

function handleClick(instance, event) {
  instance.setState({ data: event.target.value });
}

class MyComponent extends Component {
  render () {
    return <div><input type="text" onClick={ linkEvent(this, handleClick) } /><div>;
  }
}

linkEvent() offers better performance than binding an event in a class constructor and using arrow functions, so use it where possible.

Controlled Components

In HTML, form elements such as <input>, <textarea>, and <select> typically maintain their own state and update it based on user input. In Inferno, mutable state is typically kept in the state property of components, and only updated with setState().

We can combine the two by making the Inferno state be the "single source of truth". Then the Inferno component that renders a form also controls what happens in that form on subsequent user input. An input form element whose value is controlled by Inferno in this way is called a "controlled component".

Inferno Top-Level API

render (package: inferno)

import { render } from 'inferno';

render(<div />, document.getElementById("app"));

Render a virtual node into the DOM in the supplied container given the supplied virtual DOM. If the virtual node was previously rendered into the container, this will perform an update on it and only mutate the DOM as necessary, to reflect the latest Inferno virtual node.

Warning: If the container element is not empty before rendering, the content of the container will be overwritten on the initial render.

createRenderer (package: inferno)

createRenderer creates an alternative render function with a signature matching that of the first argument passed to a reduce/scan function. This allows for easier integration with reactive programming libraries, like RxJS and Most.

import { createRenderer } from 'inferno';
import { scan, map } from 'most';

const renderer = createRenderer();


// NOTE: vNodes$ represents a stream of virtual DOM node updates
scan(renderer, document.getElementById("app"), vNodes$);

See inferno-most-fp-demo for an example of how to build an app architecture around this.

createElement (package: inferno-create-element)

Creates an Inferno VNode using a similar API to that found with React's createElement()

import { Component, render } from 'inferno';
import { createElement } from 'inferno-create-element';

class BasicComponent extends Component {
  render() {
    return createElement('div', {
        className: 'basic'
      },
      createElement('span', {
        className: this.props.name
      }, 'The title is ', this.props.title)
    )
  }
}

render(
  createElement(BasicComponent, { title: 'abc' }),
  document.getElementById("app")
);

Component (package: inferno)

Class component:

import { Component } from 'inferno';

class MyComponent extends Component {
  render() {
      return <div>My Component</div>
  }
}

This is the base class for Inferno Components when they're defined using ES6 classes.

Functional component:

const MyComponent = ({ name, age }) => (
  <span>My name is: { name } and my age is: {age}</span>
);

Another way of using defaultHooks.

export function Static() {
    return <div>1</div>;
}

Static.defaultHooks = {
    onComponentShouldUpdate() {
        return false;
    }
};

Default props

export function MyFunctionalComponent({value}) {
    return <div>{value}</div>;
}

MyFunctionalComponent.defaultProps = {
    value: 10
};

Functional components are first-class functions where their first argument is the props passed through from their parent.

createVNode (package: inferno)

import { createVNode } from 'inferno';

createVNode(
  flags,
  type,
  [className],
  [...children],
  [childFlags],
  [props],
  [key],
  [ref]
)

createVNode is used to create html element's virtual node object. Typically createElement() (package: inferno-create-element), h() (package: inferno-hyperscript) or JSX are used to create VNodes for Inferno, but under the hood they all use createVNode(). Below is an example of createVNode usage:

import { VNodeFlags, ChildFlags } from 'inferno-vnode-flags';
import { createVNode, createTextVNode, render } from 'inferno';

const vNode = createVNode(VNodeFlags.HtmlElement, 'div', 'example', createTextVNode('Hello world!'), ChildFlags.HasVNodeChildren);

// <div class="example">Hello world!</div>

render(vNode, container);

createVNode arguments explained:

flags: (number) is a value from VNodeFlags, this is a numerical value that tells Inferno what the VNode describes on the page.

type: (string) is tagName for element for example 'div'

className: (string) is the class attribute ( it is separated from props because it is the most commonly used property )

children: (vNode[]|vNode) is one or array of vNodes to be added as children for this vNode

childFlags: (number) is a value from ChildFlags, this tells inferno shape of the children so normalization process can be skipped.

props: (Object) is object containing all other properties. fe: {onClick: method, 'data-attribute': 'Hello Community!}

key: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.

ref: (function) callback which is called when DOM node is added/removed from DOM.

createComponentVNode (package: 'inferno')

import { createComponentVNode } from 'inferno';

createComponentVNode(
  flags,
  type,
  [props],
  [key],
  [ref]
)

createComponentVNode is used for creating vNode for Class/Functional Component.

Example:

import { VNodeFlags, ChildFlags } from 'inferno-vnode-flags';
import { createVNode, createTextVNode, createComponentVNode, render } from 'inferno';

function MyComponent(props, context) {
  return createVNode(VNodeFlags.HtmlElement, 'div', 'example', createTextVNode(props.greeting), ChildFlags.HasVNodeChildren);
}

const vNode = createComponentVNode(VNodeFlags.ComponentFunction, MyComponent, {
  greeting: 'Hello Community!'
}, null, {
  onComponentDidMount() {
    console.log("example of did mount hook!")
  }
})

// <div class="example">Hello Community!</div>

render(vNode, container);

createComponentVNode arguments explained:

flags: (number) is a value from VNodeFlags, this is a numerical value that tells Inferno what the VNode describes on the page.

type: (Function/Class) is the class or function prototype for Component

props: (Object) properties passed to Component, can be anything

key: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.

ref: (Function|Object) this property is object for Functional Components defining all its lifecycle methods. For class Components this is function callback for ref.

createTextVNode (package: 'inferno')

createTextVNode is used for creating vNode for text nodes.

createTextVNode arguments explained: text: (string) is a value for text node to be created. key: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.

import { createTextVNode } from 'inferno';

createTextVNode(
  text,
  key
)

cloneVNode (package: inferno-clone-vnode)

This package has same API as React.cloneElement

import { cloneVNode } from 'inferno-clone-vnode';

cloneVNode(
  vNode,
  [props],
  [...children]
)

Clone and return a new Inferno VNode using a VNode as the starting point. The resulting VNode will have the original VNode's props with the new props merged in shallowly. New children will replace existing children. key and ref from the original VNode will be preserved.

cloneVNode() is almost equivalent to:

<VNode.type {...VNode.props} {...props}>{children}</VNode.type>

An example of using cloneVNode:

import { createVNode, render } from 'inferno';
import { cloneVNode } from 'inferno-clone-vnode';
import { VNodeFlags } from 'inferno-vnode-flags';

const vNode = createVNode(VNodeFlags.HtmlElement, 'div', 'example', 'Hello world!');
const newVNode = cloneVNode(vNode, { id: 'new' }); // we are adding an id prop to the VNode

render(newVNode, container);

If you're using JSX:

import { render } from 'inferno';
import { cloneVNode } from 'inferno-clone-vnode';

const vNode = <div className="example">Hello world</div>;
const newVNode = cloneVNode(vNode, { id: 'new' }); // we are adding an id prop to the VNode

render(newVNode, container);

createPortal (package: 'inferno')

HTML:

<div id="root"></div>
<div id="outside"></div>

Javascript:

const { render, Component, version, createPortal } from 'inferno';

function Outsider(props) {
	return <div>{`Hello ${props.name}!`}</div>;
}

const outsideDiv = document.getElementById('outside');
const rootDiv = document.getElementById('root');

function App() {
	return (
  	    <div>
    	    Main view
            ...
            {createPortal(<Outsider name="Inferno" />, outsideDiv)}
        </div>
    );
}


// render an instance of Clock into <body>:
render(<App />, rootDiv);

Results into:

<div id="root">
    <div>Main view ...</div>
</div>
<div id="outside">
    <div>Hello Inferno!</div>
</div>

Cool, huh? Updates (props/context) will flow into "Outsider" component from the App component the same way as any other Component. For inspiration on how to use it click here!

createRef (package: inferno)

createRef API provides shorter syntax than callback ref when timing of element is not needed.

import { Component, render, createRef } from 'inferno';

class Foobar extends Component {
  constructor(props) {
    super(props);

    // Store reference somewhere
    this.element = createRef(); // Returns object {current: null}
  }

  render() {
    return (
      <div>
        <span id="span" ref={this.element}>
          Ok
        </span>
      </div>
    );
  }
}

render(<Foobar />, container);

createFragment (package: inferno)

createFragment is the native way to createFragment vNode. createFragment(children: any, childFlags: ChildFlags, key?: string | number | null)

createFragment arguments explained:

children: (Array) Content of fragment vNode, typically array of VNodes

childFlags: (number) is a value from ChildFlags, this tells inferno shape of the children so normalization process can be skipped.

key: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.

Alternative ways to create fragment vNode are:

  • Using JSX <> ... </>, <Fragment> .... </Fragment> or <Inferno.Fragment> ... </Inferno.Fragment>
  • Using createElement API createElement(Inferno.Fragment, {key: 'test'}, ...children)
  • Using hyperscript API h(Inferno.Fragment, {key: 'test'}, children)

In the below example both fragments are identical except they have different key

import { Fragment, render, createFragment } from 'inferno';
import { ChildFlags } from 'inferno-vnode-flags';

function Foobar() {
    return (
      <div $HasKeyedChildren>
        {createFragment(
            [<div>Ok</div>, <span>1</span>],
            ChildFlags.HasNonKeyedChildren,
            'key1'
        )}
        <Fragment key="key2">
          <div>Ok</div>
          <span>1</span>
        </Fragment>
      </div>
    );
}

render(<Foobar />, container);

forwardRef (package: inferno)

forwardRef is a new mechanism to "forward" ref inside a functional Component. It can be useful if you have simple functional Components and you want to create reference to a specific element inside it.

import { forwardRef, Component, render } from 'inferno';

const FancyButton = forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

class Hello extends Component {
  render() {
    return (
      <FancyButton
        ref={btn => {
          if (btn) {
            // btn variable is the button rendered from FancyButton
          }
        }}
      >
        Click me!
      </FancyButton>
    );
  }
}

render(<Hello />, container);

hydrate (package: inferno-hydrate)

import { hydrate } from 'inferno-hydrate';

hydrate(<div />, document.getElementById("app"));

Same as render(), but is used to hydrate a container whose HTML contents were rendered by inferno-server. Inferno will attempt to attach event listeners to the existing markup.

findDOMNode (package: inferno-extras)

This feature has been moved from inferno to inferno-compat in v6. No options are needed anymore.

Note: we recommend using a ref callback on a component to find its instance, rather than using findDOMNode(). findDOMNode() cannot be used on functional components.

If a component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements. In most cases, you can attach a ref to the DOM node and avoid using findDOMNode() at all. When render returns null or false, findDOMNode() returns null. If Component has rendered fragment it returns the first element.

Inferno Flags (package: inferno-vnode-flags)

VNodeFlags:

  • VNodeFlags.HtmlElement
  • VNodeFlags.ComponentUnknown
  • VNodeFlags.ComponentClass
  • VNodeFlags.ComponentFunction
  • VNodeFlags.Text
  • VNodeFlags.SvgElement
  • VNodeFlags.InputElement
  • VNodeFlags.TextareaElement
  • VNodeFlags.SelectElement
  • VNodeFlags.Portal
  • VNodeFlags.ReCreate (JSX $ReCreate) always re-creates the vNode
  • VNodeFlags.ContentEditable
  • VNodeFlags.Fragment
  • VNodeFlags.InUse
  • VnodeFlags.ForwardRef
  • VNodeFlags.Normalized

VNodeFlags Masks:

  • VNodeFlags.ForwardRefComponent Functional component wrapped in forward ref
  • VNodeFlags.FormElement - Is form element
  • VNodeFlags.Element - Is vNode element
  • VNodeFlags.Component - Is vNode Component
  • VNodeFlags.DOMRef - Bit set when vNode holds DOM reference
  • VNodeFlags.InUseOrNormalized - VNode is used somewhere else or came from normalization process
  • VNodeFlags.ClearInUseNormalized - Opposite mask of InUse or Normalized

ChildFlags

  • ChildFlags.UnknownChildren needs Normalization
  • ChildFlags.HasInvalidChildren is invalid (null, undefined, false, true)
  • ChildFlags.HasVNodeChildren (JSX $HasVNodeChildren) is single vNode (Element/Component)
  • ChildFlags.HasNonKeyedChildren (JSX $HasNonKeyedChildren) is Array of vNodes non keyed (no nesting, no holes)
  • ChildFlags.HasKeyedChildren (JSX $HasKeyedChildren) is Array of vNodes keyed (no nesting, no holes)
  • ChildFlags.HasTextChildren (JSX $HasTextChildren) vNode contains only text

ChildFlags Masks

  • ChildFlags.MultipleChildren Is Array

renderToString (package: inferno-server)

import { renderToString } from 'inferno-server';

const string = renderToString(<div />);

Render a virtual node into an HTML string, given the supplied virtual DOM.

Functional component lifecycle events

Name Triggered when Arguments to callback
onComponentWillMount a functional component is about to mount
onComponentDidMount a functional component has mounted successfully domNode
onComponentShouldUpdate a functional component has been triggered to update lastProps, nextProps
onComponentWillUpdate a functional component is about to perform an update lastProps, nextProps
onComponentDidUpdate a functional component has performed an update lastProps, nextProps
onComponentWillUnmount a functional component is about to be unmounted domNode
onComponentDidAppear a functional component has mounted and is ready for animations domNode, props
onComponentWillDisappear a functional component is unmounted before DOM node is removed domNode, props, callback

onComponentWillDisappear has special type of argument "callback" which needs to be called when component is ready to be removed from the DOM. fe. after animations are finished.

Class component lifecycle events

All these Component lifecycle methods ( including render and setState - callback) are called with Component instance context. You don't need to "bind" these methods.

Name Triggered when Arguments to callback
componentDidMount component has been mounted successfully
componentWillMount component is about to mount
componentWillReceiveProps before render when component updates nextProps, context
shouldComponentUpdate component has been triggered to update nextProps, nextState
componentWillUpdate component is about to perform an update nextProps, nextState, context
componentDidUpdate component has performed an update lastProps, lastState, snapshot
componentWillUnmount component is about to be unmounted
getChildContext before render method, return value object is combined to sub tree context
getSnapshotBeforeUpdate before component updates, return value is sent to componentDidUpdate as 3rd parameter lastProps, lastState
static getDerivedStateFromProps before render method nextProps, state
componentDidAppear component has mounted and is ready for animations domNode
componentWillDisappear component is unmounted before DOM node is removed domNode, callback

componentWillDisappear has special type of argument "callback" which needs to be called when component is ready to be removed from the DOM. fe. after animations are finished.

Using functional lifecycle events

Functional lifecycle events must be explicitly assigned via props onto a functional component like shown below:

import { render } from 'inferno';

function mounted(domNode) {
  // [domNode] will be available for DOM nodes and components (if the component has mounted to the DOM)
}

function FunctionalComponent({ props }) {
  return <div>Hello world</div>;
}

render(
  <FunctionalComponent onComponentDidMount={ mounted } />,
  document.getElementById("app")
);

Please note: class components (ES2015 classes) from inferno do not support the same lifecycle events (they have their own lifecycle events that work as methods on the class itself).

Development vs Production modes

By default, Inferno will run in development mode. Development mode provides extra checks and better error messages at the cost of slower performance and larger code to parse. When using Inferno in a production environment, it is highly recommended that you turn off development mode.

Running Inferno on Node JS

Ensure the environment variable process.env.NODE_ENV is set to production.

Application bundling

When building your application bundle, ensure process.env.NODE_ENV is replaced with string"development" or "production" based on the workflow. It is recommended to use ts-plugin-inferno for typescript TSX compilation and babel-plugin-infeno for javascript JSX compilation.

When building for development, you may want to use inferno.dev.mjs for v9 or newer and inferno.dev.esm.js for older than v9. That bundle file contains ES6 exports for better tree-shaking support, improved error messages and added validation to help fixing possible issues during development. The file is found from package.json - dev:module entry point and the files are physically located in node_modules/inferno/dist/ folder. Remember that it is not recommended to use that file in production due to slower performance. For production usage use node_modules/inferno/dist/inferno.mjs -file for v9 or newer and node_modules/inferno/dist/inferno.esm.js -file for older than v9.

Example of Webpack configuration:

const path = require('path');
const infernoTsx = require('ts-plugin-inferno').default;

... webpack config ...

    module: {
        rules: [
            {
                test: /\.js$/, // Add "jsx" if your application uses `jsx` file extensions
                exclude: /node_modules/,
                use: [{
                    loader: 'babel-loader',
                    options: {
                        plugins: [
                            // Compile javascript JSX syntax using inferno's own plugin
                            ['babel-plugin-inferno', {imports: true}]
                        ]
                    }
                }]
            },
            {
                test: /\.ts+(|x)$/, // Compile ts and tsx extensions
                exclude: /node_modules/,
                use: [{
                    loader: 'ts-loader',
                    options: {
                        getCustomTransformers: () => ({
                            // inferno custom TSX plugin
                            after: [infernoTsx()]
                        }),
                        compilerOptions: {
                            /* typescript compiler options */
                        }
                    }
                }]
            }
        ]
    },
    resolve: {
        extensions: ['.js', '.ts', '.tsx'],
        alias: {
            // This maps import "inferno" to es6 module entry based on workflow
            inferno: path.resolve(__dirname, 'node_modules/inferno/dist', isProduction ? 'index.dev.mjs' : 'index.mjs')
        }
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV':  JSON.stringify(isProduction ? 'production' : 'development')
            }
        })
    ]

Example of Rollup configuration:

const path = require('path');
const alias = require('@rollup/plugin-alias');
const {babel} = require('@rollup/plugin-babel');
const replace = require('@rollup/plugin-replace');
const typescript = require('rollup-plugin-typescript2');
const transformInferno = require('ts-plugin-inferno').default;

... Rollup config ...
{
    input: /* entry file */,
    plugins: [
            alias({
                resolve: ['.js'],
                entries: [
                    // This maps import "inferno" to es6 module entry based on workflow
                    {find: 'inferno', replacement: path.resolve(__dirname, 'node_modules/inferno/dist', isProduction ? 'index.dev.mjs' : 'index.mjs')}
                ]
            }),
            typescript({
                include: ['*.ts+(|x)', '**/*.ts+(|x)'],
                transformers: [
                    () => ({
                        after: [transformInferno()]
                    })
                ],
                tsconfig: 'tsconfig.json',
                tsconfigOverride: {
                    /* typescript compiler options */
                }
            }),
            babel({
                babelrc: false,
                sourceMaps: isDeploy,
                plugins: [
                    // Compile javascript JSX syntax using inferno's own plugin
                    ['babel-plugin-inferno', {imports: true}]
                ],
                babelHelpers: 'bundled'
            })
    ]
}

Custom namespaces

Inferno always wants to deliver great performance. In order to do so, it has to make intelligent assumptions about the state of the DOM and the elements available to mutate. Custom namespaces conflict with this idea and change the schema of how different elements and attributes might work, so Inferno makes no attempt to support namespaces. Instead, SVG namespaces are automatically applied to elements and attributes based on their tag name.

Development

If you want to contribute code, fork this project and submit a PR from your fork. To run browser tests you need to build the repos. A complete rebuild of the repos can take >5 mins.

$ git clone [email protected]:infernojs/inferno.git
$ cd inferno && npm i
$ npm run test:node
$ npm run build
$ npm run test:browser

If you only want to run the browser tests when coding, use the following to reduce turnaround by 50-80%:

$ npm run quick-test:browser # Compiles all packages and runs browser tests
$ npm run quick-test:browser-inferno # Only compiles the inferno package and runs browser tests
$ npm run quick-test:browser-debug # Compiles all packages and runs browser tests with "debug"

Community

There is an InfernoJS Discord. You can join via https://discord.gg/SUKuhgaBpF.

Contributors

This project exists thanks to all the people who contribute. [Contribute].

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

infernojs/inferno

{
"props": {
"initialPayload": {
"allShortcutsEnabled": false,
"path": "/",
"repo": {
"id": 30161665,
"defaultBranch": "master",
"name": "inferno",
"ownerLogin": "infernojs",
"currentUserCanPush": false,
"isFork": false,
"isEmpty": false,
"createdAt": "2015-02-01T22:07:38.000Z",
"ownerAvatar": "https://avatars.githubusercontent.com/u/14214240?v=4",
"public": true,
"private": false,
"isOrgOwned": true
},
"currentUser": null,
"refInfo": {
"name": "master",
"listCacheKey": "v0:1702235859.0",
"canEdit": false,
"refType": "branch",
"currentOid": "8da43c9884b613516c3e9cb171aa4c62ab3820ca"
},
"tree": {
"items": [
{
"name": ".github",
"path": ".github",
"contentType": "directory"
},
{
"name": "browser",
"path": "browser",
"contentType": "directory"
},
{
"name": "demo/inferno-router-demo",
"path": "demo/inferno-router-demo",
"contentType": "directory",
"hasSimplifiedPath": true
},
{
"name": "docs",
"path": "docs",
"contentType": "directory"
},
{
"name": "documentation",
"path": "documentation",
"contentType": "directory"
},
{
"name": "fixtures",
"path": "fixtures",
"contentType": "directory"
},
{
"name": "packages",
"path": "packages",
"contentType": "directory"
},
{
"name": "scripts",
"path": "scripts",
"contentType": "directory"
},
{
"name": ".editorconfig",
"path": ".editorconfig",
"contentType": "file"
},
{
"name": ".eslintrc.json",
"path": ".eslintrc.json",
"contentType": "file"
},
{
"name": ".gitattributes",
"path": ".gitattributes",
"contentType": "file"
},
{
"name": ".gitignore",
"path": ".gitignore",
"contentType": "file"
},
{
"name": ".travis.yml",
"path": ".travis.yml",
"contentType": "file"
},
{
"name": "CHANGELOG.md",
"path": "CHANGELOG.md",
"contentType": "file"
},
{
"name": "CONTRIBUTING.md",
"path": "CONTRIBUTING.md",
"contentType": "file"
},
{
"name": "LICENSE.md",
"path": "LICENSE.md",
"contentType": "file"
},
{
"name": "README.md",
"path": "README.md",
"contentType": "file"
},
{
"name": "jest.config-nodom.js",
"path": "jest.config-nodom.js",
"contentType": "file"
},
{
"name": "jest.config.js",
"path": "jest.config.js",
"contentType": "file"
},
{
"name": "lerna.json",
"path": "lerna.json",
"contentType": "file"
},
{
"name": "package-lock.json",
"path": "package-lock.json",
"contentType": "file"
},
{
"name": "package.json",
"path": "package.json",
"contentType": "file"
},
{
"name": "tsconfig.json",
"path": "tsconfig.json",
"contentType": "file"
}
],
"templateDirectorySuggestionUrl": null,
"readme": null,
"totalCount": 23,
"showBranchInfobar": false
},
"fileTree": null,
"fileTreeProcessingTime": null,
"foldersToFetch": [],
"treeExpanded": false,
"symbolsExpanded": false,
"isOverview": true,
"overview": {
"banners": {
"shouldRecommendReadme": false,
"isPersonalRepo": false,
"showUseActionBanner": false,
"actionSlug": null,
"actionId": null,
"showProtectBranchBanner": false,
"publishBannersInfo": {
"dismissActionNoticePath": "/settings/dismiss-notice/publish_action_from_repo",
"releasePath": "/infernojs/inferno/releases/new?marketplace=true",
"showPublishActionBanner": false
},
"interactionLimitBanner": null,
"showInvitationBanner": false,
"inviterName": null
},
"codeButton": {
"contactPath": "/contact",
"isEnterprise": false,
"local": {
"protocolInfo": {
"httpAvailable": true,
"sshAvailable": null,
"httpUrl": "https://github.com/infernojs/inferno.git",
"showCloneWarning": null,
"sshUrl": null,
"sshCertificatesRequired": null,
"sshCertificatesAvailable": null,
"ghCliUrl": "gh repo clone infernojs/inferno",
"defaultProtocol": "http",
"newSshKeyUrl": "/settings/ssh/new",
"setProtocolPath": "/users/set_protocol"
},
"platformInfo": {
"cloneUrl": "https://desktop.github.com",
"showVisualStudioCloneButton": false,
"visualStudioCloneUrl": "https://windows.github.com",
"showXcodeCloneButton": false,
"xcodeCloneUrl": "https://developer.apple.com",
"zipballUrl": "/infernojs/inferno/archive/refs/heads/master.zip"
}
},
"newCodespacePath": "/codespaces/new?hide_repo_select=true&repo=30161665"
},
"popovers": {
"rename": null,
"renamedParentRepo": null
},
"commitCount": "6,273",
"overviewFiles": [
{
"displayName": "README.md",
"repoName": "inferno",
"refName": "master",
"path": "README.md",
"preferredFileType": "readme",
"tabName": "README",
"richText": "<article class=\"markdown-body entry-content container-lg\" itemprop=\"text\"><p align=\"center\" dir=\"auto\"><a href=\"https://infernojs.org/\" rel=\"nofollow\"><img width=\"150\" alt=\"Inferno\" title=\"Inferno\" src=\"https://user-images.githubusercontent.com/2021355/36063342-626d7ea8-0e84-11e8-84e1-f22bb3b8c4d5.png\" style=\"max-width: 100%;\"></a></p>\n<p dir=\"auto\"><a href=\"https://app.travis-ci.com/github/infernojs/inferno\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/0782860060098b3608954481402d671f4346c6c9252fac8ee1a3d0ca74d04b07/68747470733a2f2f6170702e7472617669732d63692e636f6d2f696e6665726e6f6a732f696e6665726e6f2e7376673f6272616e63683d6d6173746572\" alt=\"Build Status\" data-canonical-src=\"https://app.travis-ci.com/infernojs/inferno.svg?branch=master\" style=\"max-width: 100%;\"></a>\n<a href=\"https://coveralls.io/github/infernojs/inferno?branch=master\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/062f876d052b612a90940f3791983a2232ce463b3171a9e4a8da4a88a73bfbdd/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f696e6665726e6f6a732f696e6665726e6f2f6d61737465722e7376673f7374796c653d666c61742d737175617265\" alt=\"Coverage Status\" data-canonical-src=\"https://img.shields.io/coveralls/infernojs/inferno/master.svg?style=flat-square\" style=\"max-width: 100%;\"></a>\n<a href=\"https://github.com/infernojs/inferno/blob/master/LICENSE.md\"><img src=\"https://camo.githubusercontent.com/24fe934c0ea5701d0f45e16ba3f2e9953ed67d5f637d6a73e12e066330078b4d/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f6c2f696e6665726e6f2e7376673f7374796c653d666c61742d737175617265\" alt=\"MIT\" data-canonical-src=\"https://img.shields.io/npm/l/inferno.svg?style=flat-square\" style=\"max-width: 100%;\"></a>\n<a href=\"https://www.npmjs.com/package/inferno\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/468428fd48a4d7cbd2f2c7ccadff7c5827d732a7fdf9141e6267190774bb16b5/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f696e6665726e6f2e7376673f7374796c653d666c61742d737175617265\" alt=\"NPM\" data-canonical-src=\"https://img.shields.io/npm/v/inferno.svg?style=flat-square\" style=\"max-width: 100%;\"></a>\n<a href=\"https://www.npmjs.org/package/inferno\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/cffa491983871979bc7a374c1b630a6e5ee1b696fcb6f49dc131718014f97f94/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f696e6665726e6f2e7376673f7374796c653d666c61742d737175617265\" alt=\"npm downloads\" data-canonical-src=\"https://img.shields.io/npm/dm/inferno.svg?style=flat-square\" style=\"max-width: 100%;\"></a>\n<a href=\"https://discord.gg/SUKuhgaBpF\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/10c15806e9a75bf65ef52a650cb174f350577839b8f029cb614921d72a56998d/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3832353636393339363832333031353439362e7376673f7374796c653d666c61742d737175617265266c6162656c3d266c6f676f3d646973636f7264266c6f676f436f6c6f723d66666666666626636f6c6f723d373338394438266c6162656c436f6c6f723d364137454332\" alt=\"Discord\" data-canonical-src=\"https://img.shields.io/discord/825669396823015496.svg?style=flat-square&amp;label=&amp;logo=discord&amp;logoColor=ffffff&amp;color=7389D8&amp;labelColor=6A7EC2\" style=\"max-width: 100%;\"></a>\n<a href=\"https://unpkg.com/inferno/dist/inferno.min.js\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/85dec36e29d7f24a77603fa015dfc796cf12553cdf221fae7ecee52541cb4e41/687474703a2f2f696d672e626164676573697a652e696f2f68747470733a2f2f756e706b672e636f6d2f696e6665726e6f2f646973742f696e6665726e6f2e6d696e2e6a733f636f6d7072657373696f6e3d677a6970\" alt=\"gzip size\" data-canonical-src=\"http://img.badgesize.io/https://unpkg.com/inferno/dist/inferno.min.js?compression=gzip\" style=\"max-width: 100%;\"></a>\n<a href=\"#backers\"><img src=\"https://camo.githubusercontent.com/c9fceedef1ac0ae57cb0ab985ab0d7d8d43846a240a3f3f4589edd972a539d2a/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f6261636b6572732f62616467652e737667\" alt=\"Backers on Open Collective\" data-canonical-src=\"https://opencollective.com/inferno/backers/badge.svg\" style=\"max-width: 100%;\"></a> <a href=\"#sponsors\"><img src=\"https://camo.githubusercontent.com/0516c230bc4db11ea3a8a06bdbd64df385b9ce3760af6311cd844118e0d88577/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f72732f62616467652e737667\" alt=\"Sponsors on Open Collective\" data-canonical-src=\"https://opencollective.com/inferno/sponsors/badge.svg\" style=\"max-width: 100%;\"></a></p>\n<p dir=\"auto\">Inferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Description</h2><a id=\"user-content-description\" class=\"anchor\" aria-label=\"Permalink: Description\" href=\"#description\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">The main objective of the InfernoJS project is to provide the fastest possible <strong>runtime</strong> performance for web applications. Inferno excels at rendering real time data views or large DOM trees.</p>\n<p dir=\"auto\">The performance is achieved through multiple optimizations, for example:</p>\n<ul dir=\"auto\">\n<li>Inferno's own JSX compilers creates monomorphic <code>createVNode</code> calls, instead of <code>createElement</code> calls.\nOptimizing runtime performance of the application.\n<ul dir=\"auto\">\n<li><a href=\"https://github.com/infernojs/swc-plugin-inferno\">SWC plugin inferno</a> is a plugin for <a href=\"https://swc.rs/\" rel=\"nofollow\">SWC</a>. It can compile TSX and JSX</li>\n<li><a href=\"https://github.com/infernojs/babel-plugin-inferno\">Babel plugin inferno</a> is a plugin for <a href=\"https://babeljs.io/\" rel=\"nofollow\">BabelJs</a>. It can compile JSX.</li>\n<li><a href=\"https://github.com/infernojs/ts-plugin-inferno\">TS plugin inferno</a> is a plugin for <a href=\"https://www.typescriptlang.org/\" rel=\"nofollow\">TSC</a>. It can compile TSX.</li>\n</ul>\n</li>\n<li>Inferno's diff process uses bitwise flags to memoize the shape of objects</li>\n<li>Child nodes are normalized only when needed</li>\n<li>Special JSX flags can be used during compile time to optimize runtime performance at application level</li>\n<li>Many micro optimizations</li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Features</h2><a id=\"user-content-features\" class=\"anchor\" aria-label=\"Permalink: Features\" href=\"#features\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<ul dir=\"auto\">\n<li>Component driven + one-way data flow architecture</li>\n<li>React-like API, concepts and component lifecycle events</li>\n<li>Partial synthetic event system, normalizing events for better cross browser support</li>\n<li>Inferno's <a href=\"https://github.com/infernojs/inferno/blob/master/README.md#linkevent-package-inferno\"><code>linkEvent</code></a> feature removes the need to use arrow functions or binding event callbacks</li>\n<li>Isomorphic rendering on both client and server with <code>inferno-server</code></li>\n<li>Unlike React and Preact, Inferno has lifecycle events on functional components</li>\n<li>Unlike Preact and other React-like libraries, Inferno has controlled components for input/select/textarea elements</li>\n<li>Components can be rendered outside their current html hierarchy using <code>createPortal</code> - API</li>\n<li>Support for <a href=\"https://github.com/infernojs/inferno#browser-support\">older browsers</a> without any polyfills</li>\n<li>defaultHooks for Functional components, this way re-defining lifecycle events per usage can be avoided</li>\n<li>Inferno supports setting styles using string <code>&lt;div style=\"background-color: red\"&gt;&lt;/div&gt;</code> or using object literal syntax <code>&lt;div style={{\"background-color\": \"red\"}}&gt;&lt;/div&gt;</code>. For camelCase syntax support see <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-compat\"><code>inferno-compat</code></a>.</li>\n<li>Fragments (v6)</li>\n<li>createRef and forwardRef APIs (v6)</li>\n<li>componentDidAppear, componentWillDisappear and componentWillMove (v8) - class and function component callbacks to ease animation work, see <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-animation\">inferno-animation</a> package</li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Runtime requirements</h2><a id=\"user-content-runtime-requirements\" class=\"anchor\" aria-label=\"Permalink: Runtime requirements\" href=\"#runtime-requirements\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Inferno v9 requires following features to be present in the executing runtime:</p>\n<ul dir=\"auto\">\n<li><code>Promise</code></li>\n<li><code>String.prototype.includes()</code></li>\n<li><code>String.prototype.startsWith()</code></li>\n<li><code>Array.prototype.includes()</code></li>\n<li><code>Object.spread()</code></li>\n<li><code>for ... of</code></li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Browser support</h2><a id=\"user-content-browser-support\" class=\"anchor\" aria-label=\"Permalink: Browser support\" href=\"#browser-support\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Since version 4 we have started running our test suite <strong>without</strong> any polyfills.\nInferno is now part of <a href=\"https://saucelabs.com/\" rel=\"nofollow\">Saucelabs</a> open source program and we use their service for executing the tests.</p>\n<p dir=\"auto\">InfernoJS is actively tested with browsers listed below, however it may run well on older browsers as well.\nThis is due to limited support of browser versions in recent testing frameworks. <a href=\"https://github.com/jasmine/jasmine/blob/main/release_notes/5.0.0.md\">https://github.com/jasmine/jasmine/blob/main/release_notes/5.0.0.md</a></p>\n<p dir=\"auto\"><a href=\"https://app.saucelabs.com/open_sauce/user/Havunen/tests/vdc\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/2cfe48c2709b62d95907bdf45c6139b115e261653a421bdc884a84a196b1b739/68747470733a2f2f6170702e73617563656c6162732e636f6d2f62726f777365722d6d61747269782f486176756e656e2e737667\" alt=\"Browser Test Status\" data-canonical-src=\"https://app.saucelabs.com/browser-matrix/Havunen.svg\" style=\"max-width: 100%;\"></a></p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Migration guides</h2><a id=\"user-content-migration-guides\" class=\"anchor\" aria-label=\"Permalink: Migration guides\" href=\"#migration-guides\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<ul dir=\"auto\">\n<li><a href=\"https://github.com/infernojs/inferno/blob/master/documentation/v4-migration.md\">Inferno v4</a></li>\n<li><a href=\"https://github.com/infernojs/inferno/blob/master/documentation/v6-migration.md\">Inferno v6</a></li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Benchmarks</h2><a id=\"user-content-benchmarks\" class=\"anchor\" aria-label=\"Permalink: Benchmarks\" href=\"#benchmarks\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Live examples at <a href=\"https://infernojs.github.io/inferno\" rel=\"nofollow\">https://infernojs.github.io/inferno</a></p>\n<ul dir=\"auto\">\n<li><a href=\"https://localvoid.github.io/uibench/\" rel=\"nofollow\">UI Bench</a></li>\n<li><a href=\"https://infernojs.github.io/inferno/dbmonster/\" rel=\"nofollow\">dbmonster</a></li>\n<li><a href=\"https://krausest.github.io/js-framework-benchmark/current.html\" rel=\"nofollow\">JS Web Frameworks Benchmark (current)</a></li>\n<li><a href=\"https://github.com/marko-js/isomorphic-ui-benchmarks\">Isomorphic-UI-Benchmark</a></li>\n<li><a href=\"https://infernojs.github.io/inferno/1kcomponents/\" rel=\"nofollow\">1k Components</a></li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Code Example</h2><a id=\"user-content-code-example\" class=\"anchor\" aria-label=\"Permalink: Code Example\" href=\"#code-example\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Let's start with some code. As you can see, Inferno intentionally keeps the same design ideas as React regarding components: one-way data flow and separation of concerns.</p>\n<p dir=\"auto\">In these examples, JSX is used via the <a href=\"https://github.com/infernojs/babel-plugin-inferno\">Inferno JSX Babel Plugin</a> to provide a simple way to express Inferno virtual DOM. You do not need to use JSX, it's completely <strong>optional</strong>, you can use <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-hyperscript\">hyperscript</a> or <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-create-element\">createElement</a> (like React does).\nKeep in mind that compile time optimizations are available only for JSX.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { render } from 'inferno';\n\nconst message = &quot;Hello world&quot;;\n\nrender(\n &lt;MyComponent message={ message } /&gt;,\n document.getElementById(&quot;app&quot;)\n);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">message</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s\">\"Hello world\"</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">MyComponent</span> <span class=\"pl-c1\">message</span><span class=\"pl-c1\">=</span><span class=\"pl-kos\">{</span> <span class=\"pl-s1\">message</span> <span class=\"pl-kos\">}</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Furthermore, Inferno also uses ES6 components like React:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { render, Component } from 'inferno';\n\nclass MyComponent extends Component {\n constructor(props) {\n super(props);\n this.state = {\n counter: 0\n };\n }\n render() {\n return (\n &lt;div&gt;\n &lt;h1&gt;Header!&lt;/h1&gt;\n &lt;span&gt;Counter is at: { this.state.counter }&lt;/span&gt;\n &lt;/div&gt;\n );\n }\n}\n\nrender(\n &lt;MyComponent /&gt;,\n document.getElementById(&quot;app&quot;)\n);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">render</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">class</span> <span class=\"pl-v\">MyComponent</span> <span class=\"pl-k\">extends</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">constructor</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">super</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">state</span> <span class=\"pl-c1\">=</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">counter</span>: <span class=\"pl-c1\">0</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">h1</span><span class=\"pl-c1\">&gt;</span>Header!<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">h1</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span>Counter is at: <span class=\"pl-kos\">{</span> <span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">state</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">counter</span> <span class=\"pl-kos\">}</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">MyComponent</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Because performance is an important aspect of this library, we want to show you how to optimize your application even further.\nIn the example below we optimize diffing process by using JSX <strong>$HasVNodeChildren</strong> and <strong>$HasTextChildren</strong> to predefine children shape compile time.\nIn the MyComponent render method there is a div that contains JSX expression <code>node</code> as its content. Due to dynamic nature of Javascript\nthat variable <code>node</code> could be anything and Inferno needs to go through the normalization process to make sure there are no nested arrays or other invalid data.\nInferno offers a feature called ChildFlags for application developers to pre-define the shape of vNode's child node. In this example case\nit is using <code>$HasVNodeChildren</code> to tell the JSX compiler, that this vNode contains only single element or component vNode.\nNow inferno will not go into the normalization process runtime, but trusts the developer decision about the shape of the object and correctness of data.\nIf this contract is not kept and <code>node</code> variable contains invalid value for the pre-defined shape (fe. <code>null</code>), then application would crash runtime.\nThere is also span-element in the same render method, which content is set dynamically through <code>_getText()</code> method. There <code>$HasTextChildren</code> child-flag\nfits nicely, because the content of that given \"span\" is never anything else than text.\nAll the available child flags are documented <a href=\"https://infernojs.org/docs/guides/optimizations\" rel=\"nofollow\">here</a>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createTextVNode, render, Component } from 'inferno';\n\nclass MyComponent extends Component {\n constructor(props) {\n super(props);\n this.state = {\n counter: 0\n };\n }\n\n _getText() {\n return 'Hello!';\n }\n \n render() {\n const node = this.state.counter &gt; 0 ? &lt;div&gt;0&lt;/div&gt; : &lt;span $HasTextChildren&gt;{this._getText()}&lt;/span&gt;;\n \n return (\n &lt;div&gt;\n &lt;h1&gt;Header!&lt;/h1&gt;\n &lt;div $HasVNodeChildren&gt;{node}&lt;/div&gt;\n &lt;/div&gt;\n );\n }\n}\n\nrender(\n &lt;MyComponent /&gt;,\n document.getElementById(&quot;app&quot;)\n);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createTextVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">class</span> <span class=\"pl-v\">MyComponent</span> <span class=\"pl-k\">extends</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">constructor</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">super</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">state</span> <span class=\"pl-c1\">=</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">counter</span>: <span class=\"pl-c1\">0</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-kos\">}</span>\n\n <span class=\"pl-en\">_getText</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-s\">'Hello!'</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-kos\">}</span>\n \n <span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">const</span> <span class=\"pl-s1\">node</span> <span class=\"pl-c1\">=</span> <span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">state</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">counter</span> <span class=\"pl-c1\">&gt;</span> <span class=\"pl-c1\">0</span> ? <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>0<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span> : <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">span</span> <span class=\"pl-c1\">$HasTextChildren</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">{</span><span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">_getText</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">}</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">;</span>\n \n <span class=\"pl-k\">return</span> <span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">h1</span><span class=\"pl-c1\">&gt;</span>Header!<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">h1</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">$HasVNodeChildren</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">{</span><span class=\"pl-s1\">node</span><span class=\"pl-kos\">}</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">MyComponent</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Tear down</h3><a id=\"user-content-tear-down\" class=\"anchor\" aria-label=\"Permalink: Tear down\" href=\"#tear-down\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">To tear down inferno application you need to render null on root element.\nRendering <code>null</code> will trigger unmount lifecycle hooks for whole vDOM tree and remove global event listeners.\nIt is important to unmount unused vNode trees to free browser memory.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createTextVNode, render, Component } from 'inferno';\n\nconst rootElement = document.getElementById(&quot;app&quot;);\n\n// Start the application\nrender(\n &lt;ExampleComponent/&gt;,\n rootElement\n);\n\n// Tear down\nrender(\n null,\n rootElement\n);\n\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createTextVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">rootElement</span> <span class=\"pl-c1\">=</span> <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-c\">// Start the application</span>\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">ExampleComponent</span><span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s1\">rootElement</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-c\">// Tear down</span>\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">null</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s1\">rootElement</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">More Examples</h3><a id=\"user-content-more-examples\" class=\"anchor\" aria-label=\"Permalink: More Examples\" href=\"#more-examples\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">If you have built something using Inferno you can add them here:</p>\n<ul dir=\"auto\">\n<li><a href=\"https://jsfiddle.net/4bha7kcg/\" rel=\"nofollow\"><strong>Simple Clock</strong> (@JSFiddle)</a></li>\n<li><a href=\"https://github.com/scorsi/simple-counter-inferno-cerebral-fusebox\"><strong>Simple JS Counter</strong> (@github/scorsi)</a>: SSR Inferno (view) + Cerebral (state manager) + FuseBox (build system/bundler)</li>\n<li><a href=\"https://codesandbox.io/s/9zjo5yx8po\" rel=\"nofollow\"><strong>Online interface to TMDb movie database</strong> (@codesandbox.io)</a>: Inferno + <a href=\"https://github.com/infernojs/inferno\">Inferno hyperscript</a> (view) + <a href=\"https://github.com/visionmedia/superagent\">Superagent</a> (network requests) + Web component (<a href=\"https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements\" rel=\"nofollow\">custom elements v1</a>) + <a href=\"https://github.com/brucou/state-transducer\">state-transducer</a>\n(state machine library)</li>\n<li><a href=\"https://github.com/dessalines/lemmy\"><strong>Lemmy - a self-hostable reddit alternative</strong> (front end in Inferno)</a></li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Getting Started</h2><a id=\"user-content-getting-started\" class=\"anchor\" aria-label=\"Permalink: Getting Started\" href=\"#getting-started\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">The easiest way to get started with Inferno is by using <a href=\"https://github.com/infernojs/create-inferno-app\">Create Inferno App</a>.</p>\n<p dir=\"auto\">Alternatively, you can try any of the following:</p>\n<ul dir=\"auto\">\n<li>the <a href=\"https://github.com/infernojs/inferno-boilerplate\">Inferno Boilerplate</a> for a very simple setup.</li>\n<li>for a more advanced example demonstrating how Inferno might be used, we recommend trying out <a href=\"https://github.com/nightwolfz/inferno-starter\">Inferno Starter Project</a> by <a href=\"https://github.com/nightwolfz/\">nightwolfz</a>.</li>\n<li>for using Inferno to build a mobile app, try <a href=\"https://github.com/Rudy-Zidan/inferno-mobile\">Inferno Mobile Starter Project</a> by <a href=\"https://github.com/Rudy-Zidan\">Rudy-Zidan</a>.</li>\n<li>for <a href=\"https://www.typescriptlang.org/\" rel=\"nofollow\">TypeScript</a> support and bundling, check out <a href=\"https://github.com/infernojs/ts-plugin-inferno\">ts-plugin-inferno</a>, or <a href=\"https://github.com/infernojs/inferno-typescript-example\">inferno-typescript-example</a>.</li>\n<li>for an example of how to use Inferno in <a href=\"https://codesandbox.io/\" rel=\"nofollow\">codesandbox</a>: <a href=\"https://codesandbox.io/s/znmyj24w4p\" rel=\"nofollow\">https://codesandbox.io/s/znmyj24w4p</a></li>\n<li>for using <a href=\"https://github.com/jayy-lmao/inferno-parcel-ts\">parcel and typescript</a></li>\n</ul>\n<p dir=\"auto\">Core package:</p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm install --save inferno\"><pre>npm install --save inferno</pre></div>\n<p dir=\"auto\">Addons:</p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# server-side rendering\nnpm install --save inferno-server\n# routing\nnpm install --save inferno-router\"><pre><span class=\"pl-c\"><span class=\"pl-c\">#</span> server-side rendering</span>\nnpm install --save inferno-server\n<span class=\"pl-c\"><span class=\"pl-c\">#</span> routing</span>\nnpm install --save inferno-router</pre></div>\n<p dir=\"auto\">Pre-bundled files for browser consumption can be found on <a href=\"https://cdnjs.com/libraries/inferno\" rel=\"nofollow\">our cdnjs</a>:</p>\n<p dir=\"auto\">Or on jsDelivr:</p>\n<div class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"https://cdn.jsdelivr.net/npm/inferno@latest/dist/inferno.min.js\"><pre class=\"notranslate\"><code>https://cdn.jsdelivr.net/npm/inferno@latest/dist/inferno.min.js\n</code></pre></div>\n<p dir=\"auto\">Or on unpkg.com:</p>\n<div class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"https://unpkg.com/inferno@latest/dist/inferno.min.js\"><pre class=\"notranslate\"><code>https://unpkg.com/inferno@latest/dist/inferno.min.js\n</code></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Creating Virtual DOM</h3><a id=\"user-content-creating-virtual-dom\" class=\"anchor\" aria-label=\"Permalink: Creating Virtual DOM\" href=\"#creating-virtual-dom\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">JSX:</h4><a id=\"user-content-jsx\" class=\"anchor\" aria-label=\"Permalink: JSX:\" href=\"#jsx\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm install --save-dev babel-plugin-inferno\"><pre>npm install --save-dev babel-plugin-inferno</pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Hyperscript:</h4><a id=\"user-content-hyperscript\" class=\"anchor\" aria-label=\"Permalink: Hyperscript:\" href=\"#hyperscript\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm install --save inferno-hyperscript\"><pre>npm install --save inferno-hyperscript</pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">createElement:</h4><a id=\"user-content-createelement\" class=\"anchor\" aria-label=\"Permalink: createElement:\" href=\"#createelement\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm install --save inferno-create-element\"><pre>npm install --save inferno-create-element</pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Compatibility with existing React apps</h3><a id=\"user-content-compatibility-with-existing-react-apps\" class=\"anchor\" aria-label=\"Permalink: Compatibility with existing React apps\" href=\"#compatibility-with-existing-react-apps\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm install --save-dev inferno-compat\"><pre>npm install --save-dev inferno-compat</pre></div>\n<p dir=\"auto\">Note: Make sure you read more about <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-compat\"><code>inferno-compat</code></a> before using it.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Third-party state libraries</h2><a id=\"user-content-third-party-state-libraries\" class=\"anchor\" aria-label=\"Permalink: Third-party state libraries\" href=\"#third-party-state-libraries\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Inferno now has bindings available for some of the major state management libraries out there:</p>\n<ul dir=\"auto\">\n<li>Redux via <a href=\"https://github.com/infernojs/inferno/tree/dev/packages/inferno-redux\"><code>inferno-redux</code></a></li>\n<li>MobX via <a href=\"https://github.com/infernojs/inferno/tree/dev/packages/inferno-mobx\"><code>inferno-mobx</code></a></li>\n<li>Cerebral via <a href=\"https://github.com/cerebral/cerebral/tree/master/packages/node_modules/@cerebral/inferno\"><code>@cerebral/inferno</code></a></li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">JSX</h2><a id=\"user-content-jsx-1\" class=\"anchor\" aria-label=\"Permalink: JSX\" href=\"#jsx-1\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Inferno has its own <a href=\"https://github.com/trueadm/babel-plugin-inferno\">JSX Babel plugin</a>.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Differences from React</h2><a id=\"user-content-differences-from-react\" class=\"anchor\" aria-label=\"Permalink: Differences from React\" href=\"#differences-from-react\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<ul dir=\"auto\">\n<li>Inferno doesn't have a fully synthetic event system like React does. Inferno has a partially synthetic event system, instead opting to only delegate certain events (such as <code>onClick</code>).</li>\n<li>Inferno doesn't support React Native. Inferno was only designed for the browser/server with the DOM in mind.</li>\n<li>Inferno doesn't support legacy string refs, use <code>createRef</code> or callback <code>ref</code> API</li>\n<li>Inferno provides lifecycle events on functional components. This is a major win for people who prefer lightweight components rather than ES2015 classes.</li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Differences from Preact</h2><a id=\"user-content-differences-from-preact\" class=\"anchor\" aria-label=\"Permalink: Differences from Preact\" href=\"#differences-from-preact\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<ul dir=\"auto\">\n<li>Inferno has a partial synthetic event system, resulting in better performance via delegation of certain events.</li>\n<li>Inferno is <em>much</em> faster than Preact in rendering, updating and removing elements from the DOM. Inferno diffs against virtual DOM, rather than the real DOM (except when loading from server-side rendered content), which means it can make drastic improvements. Unfortunately, diffing against the real DOM has a 30-40% overhead cost in operations.</li>\n<li>Inferno fully supports controlled components for <code>input</code>/<code>select</code>/<code>textarea</code> elements. This prevents lots of edgecases where the virtual DOM is not the source of truth (it should always be). Preact pushes the source of truth to the DOM itself.</li>\n<li>Inferno provides lifecycle events on functional components. This is a major win for people who prefer lightweight components rather than ES2015 classes.</li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Event System</h2><a id=\"user-content-event-system\" class=\"anchor\" aria-label=\"Permalink: Event System\" href=\"#event-system\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Like React, Inferno also uses a light-weight synthetic event system in certain places (although both event systems differ massively). Inferno's event system provides highly efficient delegation and an event helper called <a href=\"https://github.com/infernojs/inferno/blob/master/README.md#linkevent-package-inferno\"><code>linkEvent</code></a>.</p>\n<p dir=\"auto\">One major difference between Inferno and React is that Inferno does not rename events or change how they work by default. Inferno only specifies that events should be camel cased, rather than lower case. Lower case events will bypass\nInferno's event system in favour of using the native event system supplied by the browser. For example, when detecting changes on an <code>&lt;input&gt;</code> element, in React you'd use <code>onChange</code>, with Inferno you'd use <code>onInput</code> instead (the\nnative DOM event is <code>oninput</code>).</p>\n<p dir=\"auto\">Available synthetic events are:</p>\n<ul dir=\"auto\">\n<li><code>onClick</code></li>\n<li><code>onDblClick</code></li>\n<li><code>onFocusIn</code></li>\n<li><code>onFocusOut</code></li>\n<li><code>onKeyDown</code></li>\n<li><code>onKeyPress</code></li>\n<li><code>onKeyUp</code></li>\n<li><code>onMouseDown</code></li>\n<li><code>onMouseMove</code></li>\n<li><code>onMouseUp</code></li>\n<li><code>onTouchEnd</code></li>\n<li><code>onTouchMove</code></li>\n<li><code>onTouchStart</code></li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>linkEvent</code> (package: <code>inferno</code>)</h3><a id=\"user-content-linkevent-package-inferno\" class=\"anchor\" aria-label=\"Permalink: linkEvent (package: inferno)\" href=\"#linkevent-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\"><code>linkEvent()</code> is a helper function that allows attachment of <code>props</code>/<code>state</code>/<code>context</code> or other data to events without needing to <code>bind()</code> them or use arrow functions/closures. This is extremely useful when dealing with events in functional components. Below is an example:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { linkEvent } from 'inferno';\n\nfunction handleClick(props, event) {\n props.validateValue(event.target.value);\n}\n\nfunction MyComponent(props) {\n return &lt;div&gt;&lt;input type=&quot;text&quot; onClick={ linkEvent(props, handleClick) } /&gt;&lt;div&gt;;\n}\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">linkEvent</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-en\">handleClick</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">event</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-s1\">props</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">validateValue</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">event</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">target</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">value</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-v\">MyComponent</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">input</span> <span class=\"pl-c1\">type</span><span class=\"pl-c1\">=</span><span class=\"pl-s\">\"text\"</span> <span class=\"pl-c1\">onClick</span><span class=\"pl-c1\">=</span><span class=\"pl-kos\">{</span> <span class=\"pl-en\">linkEvent</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">handleClick</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">}</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>;\n<span class=\"pl-kos\">}</span></pre></div>\n<p dir=\"auto\">This is an example of using it with ES2015 classes:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { linkEvent, Component } from 'inferno';\n\nfunction handleClick(instance, event) {\n instance.setState({ data: event.target.value });\n}\n\nclass MyComponent extends Component {\n render () {\n return &lt;div&gt;&lt;input type=&quot;text&quot; onClick={ linkEvent(this, handleClick) } /&gt;&lt;div&gt;;\n }\n}\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">linkEvent</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-en\">handleClick</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">instance</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">event</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-s1\">instance</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">setState</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">data</span>: <span class=\"pl-s1\">event</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">target</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">value</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-k\">class</span> <span class=\"pl-v\">MyComponent</span> <span class=\"pl-k\">extends</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">render</span> <span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">input</span> <span class=\"pl-c1\">type</span><span class=\"pl-c1\">=</span><span class=\"pl-s\">\"text\"</span> <span class=\"pl-c1\">onClick</span><span class=\"pl-c1\">=</span><span class=\"pl-kos\">{</span> <span class=\"pl-en\">linkEvent</span><span class=\"pl-kos\">(</span><span class=\"pl-smi\">this</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">handleClick</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">}</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>;\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span></pre></div>\n<p dir=\"auto\"><code>linkEvent()</code> offers better performance than binding an event in a class constructor and using arrow functions, so use it where possible.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Controlled Components</h2><a id=\"user-content-controlled-components\" class=\"anchor\" aria-label=\"Permalink: Controlled Components\" href=\"#controlled-components\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">In HTML, form elements such as <code>&lt;input&gt;</code>, <code>&lt;textarea&gt;</code>, and <code>&lt;select&gt;</code> typically maintain their own state and update it based on user input.\nIn Inferno, mutable state is typically kept in the state property of components, and only updated with <code>setState()</code>.</p>\n<p dir=\"auto\">We can combine the two by making the Inferno state be the \"single source of truth\". Then the Inferno component that renders a form also\ncontrols what happens in that form on subsequent user input. An input form element whose value is controlled by\nInferno in this way is called a \"controlled component\".</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Inferno Top-Level API</h2><a id=\"user-content-inferno-top-level-api\" class=\"anchor\" aria-label=\"Permalink: Inferno Top-Level API\" href=\"#inferno-top-level-api\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>render</code> (package: <code>inferno</code>)</h3><a id=\"user-content-render-package-inferno\" class=\"anchor\" aria-label=\"Permalink: render (package: inferno)\" href=\"#render-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { render } from 'inferno';\n\nrender(&lt;div /&gt;, document.getElementById(&quot;app&quot;));\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span> <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Render a virtual node into the DOM in the supplied container given the supplied virtual DOM. If the virtual node was previously rendered\ninto the container, this will perform an update on it and only mutate the DOM as necessary, to reflect the latest Inferno virtual node.</p>\n<p dir=\"auto\">Warning: If the container element is not empty before rendering, the content of the container will be overwritten on the initial render.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>createRenderer</code> (package: <code>inferno</code>)</h3><a id=\"user-content-createrenderer-package-inferno\" class=\"anchor\" aria-label=\"Permalink: createRenderer (package: inferno)\" href=\"#createrenderer-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\"><code>createRenderer</code> creates an alternative render function with a signature matching that of the first argument passed to a reduce/scan function. This allows for easier integration with reactive programming libraries, like <a href=\"https://github.com/ReactiveX/rxjs\">RxJS</a> and <a href=\"https://github.com/cujojs/most\">Most</a>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createRenderer } from 'inferno';\nimport { scan, map } from 'most';\n\nconst renderer = createRenderer();\n\n\n// NOTE: vNodes$ represents a stream of virtual DOM node updates\nscan(renderer, document.getElementById(&quot;app&quot;), vNodes$);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createRenderer</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">scan</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">map</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'most'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">renderer</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createRenderer</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n\n<span class=\"pl-c\">// NOTE: vNodes$ represents a stream of virtual DOM node updates</span>\n<span class=\"pl-en\">scan</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">renderer</span><span class=\"pl-kos\">,</span> <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">vNodes$</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">See <a href=\"https://github.com/joshburgess/inferno-most-fp-demo\">inferno-most-fp-demo</a> for an example of how to build an app architecture around this.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>createElement</code> (package: <code>inferno-create-element</code>)</h3><a id=\"user-content-createelement-package-inferno-create-element\" class=\"anchor\" aria-label=\"Permalink: createElement (package: inferno-create-element)\" href=\"#createelement-package-inferno-create-element\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Creates an Inferno VNode using a similar API to that found with React's <code>createElement()</code></p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\nclass BasicComponent extends Component {\n render() {\n return createElement('div', {\n className: 'basic'\n },\n createElement('span', {\n className: this.props.name\n }, 'The title is ', this.props.title)\n )\n }\n}\n\nrender(\n createElement(BasicComponent, { title: 'abc' }),\n document.getElementById(&quot;app&quot;)\n);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-v\">Component</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createElement</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-create-element'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">class</span> <span class=\"pl-v\">BasicComponent</span> <span class=\"pl-k\">extends</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-en\">createElement</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'div'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">className</span>: <span class=\"pl-s\">'basic'</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">createElement</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'span'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">className</span>: <span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">props</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">name</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'The title is '</span><span class=\"pl-kos\">,</span> <span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">props</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">title</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-en\">createElement</span><span class=\"pl-kos\">(</span><span class=\"pl-v\">BasicComponent</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">title</span>: <span class=\"pl-s\">'abc'</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>Component</code> (package: <code>inferno</code>)</h3><a id=\"user-content-component-package-inferno\" class=\"anchor\" aria-label=\"Permalink: Component (package: inferno)\" href=\"#component-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\"><strong>Class component:</strong></p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { Component } from 'inferno';\n\nclass MyComponent extends Component {\n render() {\n return &lt;div&gt;My Component&lt;/div&gt;\n }\n}\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">class</span> <span class=\"pl-v\">MyComponent</span> <span class=\"pl-k\">extends</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>My Component<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span></pre></div>\n<p dir=\"auto\">This is the base class for Inferno Components when they're defined using ES6 classes.</p>\n<p dir=\"auto\"><strong>Functional component:</strong></p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const MyComponent = ({ name, age }) =&gt; (\n &lt;span&gt;My name is: { name } and my age is: {age}&lt;/span&gt;\n);\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-v\">MyComponent</span> <span class=\"pl-c1\">=</span> <span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> name<span class=\"pl-kos\">,</span> age <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span>My name is: <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">name</span> <span class=\"pl-kos\">}</span> and my age is: <span class=\"pl-kos\">{</span><span class=\"pl-s1\">age</span><span class=\"pl-kos\">}</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Another way of using defaultHooks.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"export function Static() {\n return &lt;div&gt;1&lt;/div&gt;;\n}\n\nStatic.defaultHooks = {\n onComponentShouldUpdate() {\n return false;\n }\n};\"><pre><span class=\"pl-k\">export</span> <span class=\"pl-k\">function</span> <span class=\"pl-v\">Static</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>1<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-v\">Static</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">defaultHooks</span> <span class=\"pl-c1\">=</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">onComponentShouldUpdate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-c1\">false</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Default props</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"export function MyFunctionalComponent({value}) {\n return &lt;div&gt;{value}&lt;/div&gt;;\n}\n\nMyFunctionalComponent.defaultProps = {\n value: 10\n};\n\"><pre><span class=\"pl-k\">export</span> <span class=\"pl-k\">function</span> <span class=\"pl-v\">MyFunctionalComponent</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>value<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">{</span><span class=\"pl-s1\">value</span><span class=\"pl-kos\">}</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-v\">MyFunctionalComponent</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">defaultProps</span> <span class=\"pl-c1\">=</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">value</span>: <span class=\"pl-c1\">10</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Functional components are first-class functions where their first argument is the <code>props</code> passed through from their parent.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>createVNode</code> (package: <code>inferno</code>)</h3><a id=\"user-content-createvnode-package-inferno\" class=\"anchor\" aria-label=\"Permalink: createVNode (package: inferno)\" href=\"#createvnode-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createVNode } from 'inferno';\n\ncreateVNode(\n flags,\n type,\n [className],\n [...children],\n [childFlags],\n [props],\n [key],\n [ref]\n)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createVNode</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-en\">createVNode</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-s1\">flags</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s1\">type</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">className</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span>...<span class=\"pl-s1\">children</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">childFlags</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">key</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">ref</span><span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">createVNode is used to create html element's virtual node object. Typically <code>createElement()</code> (package: <code>inferno-create-element</code>), <code>h()</code> (package: <code>inferno-hyperscript</code>) or JSX are used to create\n<code>VNode</code>s for Inferno, but under the hood they all use <code>createVNode()</code>. Below is an example of <code>createVNode</code> usage:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { VNodeFlags, ChildFlags } from 'inferno-vnode-flags';\nimport { createVNode, createTextVNode, render } from 'inferno';\n\nconst vNode = createVNode(VNodeFlags.HtmlElement, 'div', 'example', createTextVNode('Hello world!'), ChildFlags.HasVNodeChildren);\n\n// &lt;div class=&quot;example&quot;&gt;Hello world!&lt;/div&gt;\n\nrender(vNode, container);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-v\">VNodeFlags</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">ChildFlags</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-vnode-flags'</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">createTextVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">vNode</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createVNode</span><span class=\"pl-kos\">(</span><span class=\"pl-v\">VNodeFlags</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">HtmlElement</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'div'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'example'</span><span class=\"pl-kos\">,</span> <span class=\"pl-en\">createTextVNode</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'Hello world!'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">ChildFlags</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">HasVNodeChildren</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-c\">// &lt;div class=\"example\"&gt;Hello world!&lt;/div&gt;</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">vNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">container</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\"><code>createVNode</code> arguments explained:</p>\n<p dir=\"auto\"><code>flags</code>: (number) is a value from <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags\"><code>VNodeFlags</code></a>, this is a numerical value that tells Inferno what the VNode describes on the page.</p>\n<p dir=\"auto\"><code>type</code>: (string) is tagName for element for example 'div'</p>\n<p dir=\"auto\"><code>className</code>: (string) is the class attribute ( it is separated from props because it is the most commonly used property )</p>\n<p dir=\"auto\"><code>children</code>: (vNode[]|vNode) is one or array of vNodes to be added as children for this vNode</p>\n<p dir=\"auto\"><code>childFlags</code>: (number) is a value from <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags\"><code>ChildFlags</code></a>, this tells inferno shape of the children so normalization process can be skipped.</p>\n<p dir=\"auto\"><code>props</code>: (Object) is object containing all other properties. fe: <code>{onClick: method, 'data-attribute': 'Hello Community!}</code></p>\n<p dir=\"auto\"><code>key</code>: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.</p>\n<p dir=\"auto\"><code>ref</code>: (function) callback which is called when DOM node is added/removed from DOM.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>createComponentVNode</code> (package: 'inferno')</h3><a id=\"user-content-createcomponentvnode-package-inferno\" class=\"anchor\" aria-label=\"Permalink: createComponentVNode (package: 'inferno')\" href=\"#createcomponentvnode-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createComponentVNode } from 'inferno';\n\ncreateComponentVNode(\n flags,\n type,\n [props],\n [key],\n [ref]\n)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createComponentVNode</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-en\">createComponentVNode</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-s1\">flags</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s1\">type</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">key</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">ref</span><span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">createComponentVNode is used for creating vNode for Class/Functional Component.</p>\n<p dir=\"auto\">Example:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { VNodeFlags, ChildFlags } from 'inferno-vnode-flags';\nimport { createVNode, createTextVNode, createComponentVNode, render } from 'inferno';\n\nfunction MyComponent(props, context) {\n return createVNode(VNodeFlags.HtmlElement, 'div', 'example', createTextVNode(props.greeting), ChildFlags.HasVNodeChildren);\n}\n\nconst vNode = createComponentVNode(VNodeFlags.ComponentFunction, MyComponent, {\n greeting: 'Hello Community!'\n}, null, {\n onComponentDidMount() {\n console.log(&quot;example of did mount hook!&quot;)\n }\n})\n\n// &lt;div class=&quot;example&quot;&gt;Hello Community!&lt;/div&gt;\n\nrender(vNode, container);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-v\">VNodeFlags</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">ChildFlags</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-vnode-flags'</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">createTextVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">createComponentVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-v\">MyComponent</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">context</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-en\">createVNode</span><span class=\"pl-kos\">(</span><span class=\"pl-v\">VNodeFlags</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">HtmlElement</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'div'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'example'</span><span class=\"pl-kos\">,</span> <span class=\"pl-en\">createTextVNode</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">greeting</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">ChildFlags</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">HasVNodeChildren</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">vNode</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createComponentVNode</span><span class=\"pl-kos\">(</span><span class=\"pl-v\">VNodeFlags</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">ComponentFunction</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">MyComponent</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">greeting</span>: <span class=\"pl-s\">'Hello Community!'</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">null</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">onComponentDidMount</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"example of did mount hook!\"</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n\n<span class=\"pl-c\">// &lt;div class=\"example\"&gt;Hello Community!&lt;/div&gt;</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">vNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">container</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\"><code>createComponentVNode</code> arguments explained:</p>\n<p dir=\"auto\"><code>flags</code>: (number) is a value from <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags\"><code>VNodeFlags</code></a>, this is a numerical value that tells Inferno what the VNode describes on the page.</p>\n<p dir=\"auto\"><code>type</code>: (Function/Class) is the class or function prototype for Component</p>\n<p dir=\"auto\"><code>props</code>: (Object) properties passed to Component, can be anything</p>\n<p dir=\"auto\"><code>key</code>: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.</p>\n<p dir=\"auto\"><code>ref</code>: (Function|Object) this property is object for Functional Components defining all its lifecycle methods. For class Components this is function callback for ref.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>createTextVNode</code> (package: 'inferno')</h3><a id=\"user-content-createtextvnode-package-inferno\" class=\"anchor\" aria-label=\"Permalink: createTextVNode (package: 'inferno')\" href=\"#createtextvnode-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">createTextVNode is used for creating vNode for text nodes.</p>\n<p dir=\"auto\"><code>createTextVNode</code> arguments explained:\ntext: (string) is a value for text node to be created.\nkey: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createTextVNode } from 'inferno';\n\ncreateTextVNode(\n text,\n key\n)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createTextVNode</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-en\">createTextVNode</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-s1\">text</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s1\">key</span>\n<span class=\"pl-kos\">)</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>cloneVNode</code> (package: <code>inferno-clone-vnode</code>)</h3><a id=\"user-content-clonevnode-package-inferno-clone-vnode\" class=\"anchor\" aria-label=\"Permalink: cloneVNode (package: inferno-clone-vnode)\" href=\"#clonevnode-package-inferno-clone-vnode\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">This package has same API as React.cloneElement</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { cloneVNode } from 'inferno-clone-vnode';\n\ncloneVNode(\n vNode,\n [props],\n [...children]\n)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">cloneVNode</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-clone-vnode'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-en\">cloneVNode</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-s1\">vNode</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span>...<span class=\"pl-s1\">children</span><span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">Clone and return a new Inferno <code>VNode</code> using a <code>VNode</code> as the starting point. The resulting <code>VNode</code> will have the original <code>VNode</code>'s props with the new props merged in shallowly. New children will replace existing children. key and ref from the original <code>VNode</code> will be preserved.</p>\n<p dir=\"auto\"><code>cloneVNode()</code> is almost equivalent to:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"&lt;VNode.type {...VNode.props} {...props}&gt;{children}&lt;/VNode.type&gt;\"><pre><span class=\"pl-c1\">&lt;</span><span class=\"pl-v\">VNode</span><span class=\"pl-kos\">.</span><span class=\"pl-s1\">type</span> <span class=\"pl-kos\">{</span>...<span class=\"pl-v\">VNode</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">props</span><span class=\"pl-kos\">}</span> <span class=\"pl-kos\">{</span>...<span class=\"pl-s1\">props</span><span class=\"pl-kos\">}</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">{</span><span class=\"pl-s1\">children</span><span class=\"pl-kos\">}</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-v\">VNode</span><span class=\"pl-kos\">.</span><span class=\"pl-s1\">type</span><span class=\"pl-c1\">&gt;</span></pre></div>\n<p dir=\"auto\">An example of using <code>cloneVNode</code>:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createVNode, render } from 'inferno';\nimport { cloneVNode } from 'inferno-clone-vnode';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst vNode = createVNode(VNodeFlags.HtmlElement, 'div', 'example', 'Hello world!');\nconst newVNode = cloneVNode(vNode, { id: 'new' }); // we are adding an id prop to the VNode\n\nrender(newVNode, container);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">cloneVNode</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-clone-vnode'</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-v\">VNodeFlags</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-vnode-flags'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">vNode</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createVNode</span><span class=\"pl-kos\">(</span><span class=\"pl-v\">VNodeFlags</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">HtmlElement</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'div'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'example'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'Hello world!'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">newVNode</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">cloneVNode</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">vNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">id</span>: <span class=\"pl-s\">'new'</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// we are adding an id prop to the VNode</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">newVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">container</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">If you're using JSX:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { render } from 'inferno';\nimport { cloneVNode } from 'inferno-clone-vnode';\n\nconst vNode = &lt;div className=&quot;example&quot;&gt;Hello world&lt;/div&gt;;\nconst newVNode = cloneVNode(vNode, { id: 'new' }); // we are adding an id prop to the VNode\n\nrender(newVNode, container);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">cloneVNode</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-clone-vnode'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">vNode</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">className</span><span class=\"pl-c1\">=</span><span class=\"pl-s\">\"example\"</span><span class=\"pl-c1\">&gt;</span>Hello world<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">newVNode</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">cloneVNode</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">vNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">id</span>: <span class=\"pl-s\">'new'</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// we are adding an id prop to the VNode</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">newVNode</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">container</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>createPortal</code> (package: 'inferno')</h3><a id=\"user-content-createportal-package-inferno\" class=\"anchor\" aria-label=\"Permalink: createPortal (package: 'inferno')\" href=\"#createportal-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">HTML:</p>\n<div class=\"highlight highlight-text-html-basic notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"&lt;div id=&quot;root&quot;&gt;&lt;/div&gt;\n&lt;div id=&quot;outside&quot;&gt;&lt;/div&gt;\"><pre><span class=\"pl-kos\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">id</span>=\"<span class=\"pl-s\">root</span>\"<span class=\"pl-kos\">&gt;</span><span class=\"pl-kos\">&lt;/</span><span class=\"pl-ent\">div</span><span class=\"pl-kos\">&gt;</span>\n<span class=\"pl-kos\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">id</span>=\"<span class=\"pl-s\">outside</span>\"<span class=\"pl-kos\">&gt;</span><span class=\"pl-kos\">&lt;/</span><span class=\"pl-ent\">div</span><span class=\"pl-kos\">&gt;</span></pre></div>\n<p dir=\"auto\">Javascript:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const { render, Component, version, createPortal } from 'inferno';\n\nfunction Outsider(props) {\n\treturn &lt;div&gt;{`Hello ${props.name}!`}&lt;/div&gt;;\n}\n\nconst outsideDiv = document.getElementById('outside');\nconst rootDiv = document.getElementById('root');\n\nfunction App() {\n\treturn (\n \t &lt;div&gt;\n \t Main view\n ...\n {createPortal(&lt;Outsider name=&quot;Inferno&quot; /&gt;, outsideDiv)}\n &lt;/div&gt;\n );\n}\n\n\n// render an instance of Clock into &lt;body&gt;:\nrender(&lt;App /&gt;, rootDiv);\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-kos\">{</span> render<span class=\"pl-kos\">,</span> Component<span class=\"pl-kos\">,</span> version<span class=\"pl-kos\">,</span> createPortal <span class=\"pl-kos\">}</span> <span class=\"pl-s1\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-v\">Outsider</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n\t<span class=\"pl-k\">return</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">{</span><span class=\"pl-s\">`Hello <span class=\"pl-s1\"><span class=\"pl-kos\">${</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">name</span><span class=\"pl-kos\">}</span></span>!`</span><span class=\"pl-kos\">}</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">outsideDiv</span> <span class=\"pl-c1\">=</span> <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'outside'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">rootDiv</span> <span class=\"pl-c1\">=</span> <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'root'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-v\">App</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n\t<span class=\"pl-k\">return</span> <span class=\"pl-kos\">(</span>\n \t <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n \t Main view\n ...\n <span class=\"pl-kos\">{</span><span class=\"pl-en\">createPortal</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">Outsider</span> <span class=\"pl-c1\">name</span><span class=\"pl-c1\">=</span><span class=\"pl-s\">\"Inferno\"</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">outsideDiv</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">}</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n\n<span class=\"pl-c\">// render an instance of Clock into &lt;body&gt;:</span>\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">App</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">rootDiv</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Results into:</p>\n<div class=\"highlight highlight-text-html-basic notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"&lt;div id=&quot;root&quot;&gt;\n &lt;div&gt;Main view ...&lt;/div&gt;\n&lt;/div&gt;\n&lt;div id=&quot;outside&quot;&gt;\n &lt;div&gt;Hello Inferno!&lt;/div&gt;\n&lt;/div&gt;\"><pre><span class=\"pl-kos\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">id</span>=\"<span class=\"pl-s\">root</span>\"<span class=\"pl-kos\">&gt;</span>\n <span class=\"pl-kos\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-kos\">&gt;</span>Main view ...<span class=\"pl-kos\">&lt;/</span><span class=\"pl-ent\">div</span><span class=\"pl-kos\">&gt;</span>\n<span class=\"pl-kos\">&lt;/</span><span class=\"pl-ent\">div</span><span class=\"pl-kos\">&gt;</span>\n<span class=\"pl-kos\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">id</span>=\"<span class=\"pl-s\">outside</span>\"<span class=\"pl-kos\">&gt;</span>\n <span class=\"pl-kos\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-kos\">&gt;</span>Hello Inferno!<span class=\"pl-kos\">&lt;/</span><span class=\"pl-ent\">div</span><span class=\"pl-kos\">&gt;</span>\n<span class=\"pl-kos\">&lt;/</span><span class=\"pl-ent\">div</span><span class=\"pl-kos\">&gt;</span></pre></div>\n<p dir=\"auto\">Cool, huh? Updates (props/context) will flow into \"Outsider\" component from the App component the same way as any other Component.\nFor inspiration on how to use it click <a href=\"https://hackernoon.com/using-a-react-16-portal-to-do-something-cool-2a2d627b0202\" rel=\"nofollow\">here</a>!</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>createRef</code> (package: <code>inferno</code>)</h3><a id=\"user-content-createref-package-inferno\" class=\"anchor\" aria-label=\"Permalink: createRef (package: inferno)\" href=\"#createref-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">createRef API provides shorter syntax than callback ref when timing of element is not needed.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { Component, render, createRef } from 'inferno';\n\nclass Foobar extends Component {\n constructor(props) {\n super(props);\n\n // Store reference somewhere\n this.element = createRef(); // Returns object {current: null}\n }\n\n render() {\n return (\n &lt;div&gt;\n &lt;span id=&quot;span&quot; ref={this.element}&gt;\n Ok\n &lt;/span&gt;\n &lt;/div&gt;\n );\n }\n}\n\nrender(&lt;Foobar /&gt;, container);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-v\">Component</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">createRef</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">class</span> <span class=\"pl-v\">Foobar</span> <span class=\"pl-k\">extends</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">constructor</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">super</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n <span class=\"pl-c\">// Store reference somewhere</span>\n <span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">element</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createRef</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// Returns object {current: null}</span>\n <span class=\"pl-kos\">}</span>\n\n <span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">span</span> <span class=\"pl-c1\">id</span><span class=\"pl-c1\">=</span><span class=\"pl-s\">\"span\"</span> <span class=\"pl-c1\">ref</span><span class=\"pl-c1\">=</span><span class=\"pl-kos\">{</span><span class=\"pl-smi\">this</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">element</span><span class=\"pl-kos\">}</span><span class=\"pl-c1\">&gt;</span>\n Ok\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">Foobar</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">container</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>createFragment</code> (package: <code>inferno</code>)</h3><a id=\"user-content-createfragment-package-inferno\" class=\"anchor\" aria-label=\"Permalink: createFragment (package: inferno)\" href=\"#createfragment-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">createFragment is the native way to createFragment vNode. <code>createFragment(children: any, childFlags: ChildFlags, key?: string | number | null)</code></p>\n<p dir=\"auto\"><code>createFragment</code> arguments explained:</p>\n<p dir=\"auto\"><code>children</code>: (Array) Content of fragment vNode, typically array of VNodes</p>\n<p dir=\"auto\"><code>childFlags</code>: (number) is a value from <a href=\"https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags\"><code>ChildFlags</code></a>, this tells inferno shape of the children so normalization process can be skipped.</p>\n<p dir=\"auto\"><code>key</code>: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.</p>\n<p dir=\"auto\">Alternative ways to create fragment vNode are:</p>\n<ul dir=\"auto\">\n<li>Using JSX <code>&lt;&gt; ... &lt;/&gt;</code>, <code>&lt;Fragment&gt; .... &lt;/Fragment&gt;</code> or <code>&lt;Inferno.Fragment&gt; ... &lt;/Inferno.Fragment&gt;</code></li>\n<li>Using createElement API <code>createElement(Inferno.Fragment, {key: 'test'}, ...children)</code></li>\n<li>Using hyperscript API <code>h(Inferno.Fragment, {key: 'test'}, children)</code></li>\n</ul>\n<p dir=\"auto\">In the below example both fragments are identical except they have different key</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { Fragment, render, createFragment } from 'inferno';\nimport { ChildFlags } from 'inferno-vnode-flags';\n\nfunction Foobar() {\n return (\n &lt;div $HasKeyedChildren&gt;\n {createFragment(\n [&lt;div&gt;Ok&lt;/div&gt;, &lt;span&gt;1&lt;/span&gt;],\n ChildFlags.HasNonKeyedChildren,\n 'key1'\n )}\n &lt;Fragment key=&quot;key2&quot;&gt;\n &lt;div&gt;Ok&lt;/div&gt;\n &lt;span&gt;1&lt;/span&gt;\n &lt;/Fragment&gt;\n &lt;/div&gt;\n );\n}\n\nrender(&lt;Foobar /&gt;, container);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-v\">Fragment</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">createFragment</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-v\">ChildFlags</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-vnode-flags'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-v\">Foobar</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">$HasKeyedChildren</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">{</span><span class=\"pl-en\">createFragment</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>Ok<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span>1<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-v\">ChildFlags</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">HasNonKeyedChildren</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s\">'key1'</span>\n <span class=\"pl-kos\">)</span><span class=\"pl-kos\">}</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">Fragment</span> <span class=\"pl-c1\">key</span><span class=\"pl-c1\">=</span><span class=\"pl-s\">\"key2\"</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>Ok<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span>1<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">span</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">Fragment</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">Foobar</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">container</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>forwardRef</code> (package: <code>inferno</code>)</h3><a id=\"user-content-forwardref-package-inferno\" class=\"anchor\" aria-label=\"Permalink: forwardRef (package: inferno)\" href=\"#forwardref-package-inferno\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">forwardRef is a new mechanism to \"forward\" ref inside a functional Component.\nIt can be useful if you have simple functional Components and you want to create reference to a specific element inside it.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { forwardRef, Component, render } from 'inferno';\n\nconst FancyButton = forwardRef((props, ref) =&gt; (\n &lt;button ref={ref} className=&quot;FancyButton&quot;&gt;\n {props.children}\n &lt;/button&gt;\n));\n\nclass Hello extends Component {\n render() {\n return (\n &lt;FancyButton\n ref={btn =&gt; {\n if (btn) {\n // btn variable is the button rendered from FancyButton\n }\n }}\n &gt;\n Click me!\n &lt;/FancyButton&gt;\n );\n }\n}\n\nrender(&lt;Hello /&gt;, container);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">forwardRef</span><span class=\"pl-kos\">,</span> <span class=\"pl-v\">Component</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-v\">FancyButton</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">forwardRef</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">ref</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">button</span> <span class=\"pl-c1\">ref</span><span class=\"pl-c1\">=</span><span class=\"pl-kos\">{</span><span class=\"pl-s1\">ref</span><span class=\"pl-kos\">}</span> <span class=\"pl-c1\">className</span><span class=\"pl-c1\">=</span><span class=\"pl-s\">\"FancyButton\"</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">{</span><span class=\"pl-s1\">props</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">children</span><span class=\"pl-kos\">}</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">button</span><span class=\"pl-c1\">&gt;</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">class</span> <span class=\"pl-v\">Hello</span> <span class=\"pl-k\">extends</span> <span class=\"pl-v\">Component</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-v\">FancyButton</span>\n <span class=\"pl-c1\">ref</span><span class=\"pl-c1\">=</span><span class=\"pl-kos\">{</span><span class=\"pl-s1\">btn</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">if</span> <span class=\"pl-kos\">(</span><span class=\"pl-s1\">btn</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c\">// btn variable is the button rendered from FancyButton</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">}</span>\n <span class=\"pl-c1\">&gt;</span>\n Click me!\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-v\">FancyButton</span><span class=\"pl-c1\">&gt;</span>\n <span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">Hello</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">container</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>hydrate</code> (package: <code>inferno-hydrate</code>)</h3><a id=\"user-content-hydrate-package-inferno-hydrate\" class=\"anchor\" aria-label=\"Permalink: hydrate (package: inferno-hydrate)\" href=\"#hydrate-package-inferno-hydrate\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { hydrate } from 'inferno-hydrate';\n\nhydrate(&lt;div /&gt;, document.getElementById(&quot;app&quot;));\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">hydrate</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-hydrate'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-en\">hydrate</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span> <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Same as <code>render()</code>, but is used to hydrate a container whose HTML contents were rendered by <code>inferno-server</code>. Inferno will attempt to attach event listeners to the existing markup.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>findDOMNode</code> (package: <code>inferno-extras</code>)</h3><a id=\"user-content-finddomnode-package-inferno-extras\" class=\"anchor\" aria-label=\"Permalink: findDOMNode (package: inferno-extras)\" href=\"#finddomnode-package-inferno-extras\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">This feature has been moved from inferno to inferno-compat in v6. No options are needed anymore.</p>\n<p dir=\"auto\">Note: we recommend using a <code>ref</code> callback on a component to find its instance, rather than using <code>findDOMNode()</code>. <code>findDOMNode()</code> cannot be used on functional components.</p>\n<p dir=\"auto\">If a component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements.\nIn most cases, you can attach a ref to the DOM node and avoid using <code>findDOMNode()</code> at all. When render returns null or false, <code>findDOMNode()</code> returns null.\nIf Component has rendered fragment it returns the first element.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Inferno Flags (package: inferno-vnode-flags)</h3><a id=\"user-content-inferno-flags-package-inferno-vnode-flags\" class=\"anchor\" aria-label=\"Permalink: Inferno Flags (package: inferno-vnode-flags)\" href=\"#inferno-flags-package-inferno-vnode-flags\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\"><strong>VNodeFlags:</strong></p>\n<ul dir=\"auto\">\n<li><code>VNodeFlags.HtmlElement</code></li>\n<li><code>VNodeFlags.ComponentUnknown</code></li>\n<li><code>VNodeFlags.ComponentClass</code></li>\n<li><code>VNodeFlags.ComponentFunction</code></li>\n<li><code>VNodeFlags.Text</code></li>\n<li><code>VNodeFlags.SvgElement</code></li>\n<li><code>VNodeFlags.InputElement</code></li>\n<li><code>VNodeFlags.TextareaElement</code></li>\n<li><code>VNodeFlags.SelectElement</code></li>\n<li><code>VNodeFlags.Portal</code></li>\n<li><code>VNodeFlags.ReCreate</code> (JSX <strong>$ReCreate</strong>) always re-creates the vNode</li>\n<li><code>VNodeFlags.ContentEditable</code></li>\n<li><code>VNodeFlags.Fragment</code></li>\n<li><code>VNodeFlags.InUse</code></li>\n<li><code>VnodeFlags.ForwardRef</code></li>\n<li><code>VNodeFlags.Normalized</code></li>\n</ul>\n<p dir=\"auto\"><strong>VNodeFlags Masks:</strong></p>\n<ul dir=\"auto\">\n<li><code>VNodeFlags.ForwardRefComponent</code> Functional component wrapped in forward ref</li>\n<li><code>VNodeFlags.FormElement</code> - Is form element</li>\n<li><code>VNodeFlags.Element</code> - Is vNode element</li>\n<li><code>VNodeFlags.Component</code> - Is vNode Component</li>\n<li><code>VNodeFlags.DOMRef</code> - Bit set when vNode holds DOM reference</li>\n<li><code>VNodeFlags.InUseOrNormalized</code> - VNode is used somewhere else or came from normalization process</li>\n<li><code>VNodeFlags.ClearInUseNormalized</code> - Opposite mask of InUse or Normalized</li>\n</ul>\n<p dir=\"auto\"><strong>ChildFlags</strong></p>\n<ul dir=\"auto\">\n<li><code>ChildFlags.UnknownChildren</code> needs Normalization</li>\n<li><code>ChildFlags.HasInvalidChildren</code> is invalid (null, undefined, false, true)</li>\n<li><code>ChildFlags.HasVNodeChildren</code> (JSX <strong>$HasVNodeChildren</strong>) is single vNode (Element/Component)</li>\n<li><code>ChildFlags.HasNonKeyedChildren</code> (JSX <strong>$HasNonKeyedChildren</strong>) is Array of vNodes non keyed (no nesting, no holes)</li>\n<li><code>ChildFlags.HasKeyedChildren</code> (JSX <strong>$HasKeyedChildren</strong>) is Array of vNodes keyed (no nesting, no holes)</li>\n<li><code>ChildFlags.HasTextChildren</code> (JSX <strong>$HasTextChildren</strong>) vNode contains only text</li>\n</ul>\n<p dir=\"auto\"><strong>ChildFlags Masks</strong></p>\n<ul dir=\"auto\">\n<li><code>ChildFlags.MultipleChildren</code> Is Array</li>\n</ul>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"><code>renderToString</code> (package: <code>inferno-server</code>)</h3><a id=\"user-content-rendertostring-package-inferno-server\" class=\"anchor\" aria-label=\"Permalink: renderToString (package: inferno-server)\" href=\"#rendertostring-package-inferno-server\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { renderToString } from 'inferno-server';\n\nconst string = renderToString(&lt;div /&gt;);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">renderToString</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno-server'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">string</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">renderToString</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Render a virtual node into an HTML string, given the supplied virtual DOM.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Functional component lifecycle events</h2><a id=\"user-content-functional-component-lifecycle-events\" class=\"anchor\" aria-label=\"Permalink: Functional component lifecycle events\" href=\"#functional-component-lifecycle-events\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<table>\n<thead>\n<tr>\n<th>Name</th>\n<th>Triggered when</th>\n<th>Arguments to callback</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>onComponentWillMount</code></td>\n<td>a functional component is about to mount</td>\n<td></td>\n</tr>\n<tr>\n<td><code>onComponentDidMount</code></td>\n<td>a functional component has mounted successfully</td>\n<td><code>domNode</code></td>\n</tr>\n<tr>\n<td><code>onComponentShouldUpdate</code></td>\n<td>a functional component has been triggered to update</td>\n<td><code>lastProps, nextProps</code></td>\n</tr>\n<tr>\n<td><code>onComponentWillUpdate</code></td>\n<td>a functional component is about to perform an update</td>\n<td><code>lastProps, nextProps</code></td>\n</tr>\n<tr>\n<td><code>onComponentDidUpdate</code></td>\n<td>a functional component has performed an update</td>\n<td><code>lastProps, nextProps</code></td>\n</tr>\n<tr>\n<td><code>onComponentWillUnmount</code></td>\n<td>a functional component is about to be unmounted</td>\n<td><code>domNode</code></td>\n</tr>\n<tr>\n<td><code>onComponentDidAppear</code></td>\n<td>a functional component has mounted and is ready for animations</td>\n<td><code>domNode, props</code></td>\n</tr>\n<tr>\n<td><code>onComponentWillDisappear</code></td>\n<td>a functional component is unmounted before DOM node is removed</td>\n<td><code>domNode, props, callback</code></td>\n</tr>\n</tbody>\n</table>\n<p dir=\"auto\">onComponentWillDisappear has special type of argument \"callback\" which needs to be called when component is ready to be removed from the DOM. fe. after animations are finished.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Class component lifecycle events</h2><a id=\"user-content-class-component-lifecycle-events\" class=\"anchor\" aria-label=\"Permalink: Class component lifecycle events\" href=\"#class-component-lifecycle-events\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">All these Component lifecycle methods ( including <code>render</code> and <code>setState - callback</code>) are called with Component instance context. You don't need to \"bind\" these methods.</p>\n<table>\n<thead>\n<tr>\n<th>Name</th>\n<th>Triggered when</th>\n<th>Arguments to callback</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>componentDidMount</code></td>\n<td>component has been mounted successfully</td>\n<td></td>\n</tr>\n<tr>\n<td><code>componentWillMount</code></td>\n<td>component is about to mount</td>\n<td></td>\n</tr>\n<tr>\n<td><code>componentWillReceiveProps</code></td>\n<td>before render when component updates</td>\n<td><code>nextProps, context</code></td>\n</tr>\n<tr>\n<td><code>shouldComponentUpdate</code></td>\n<td>component has been triggered to update</td>\n<td><code>nextProps, nextState</code></td>\n</tr>\n<tr>\n<td><code>componentWillUpdate</code></td>\n<td>component is about to perform an update</td>\n<td><code>nextProps, nextState, context</code></td>\n</tr>\n<tr>\n<td><code>componentDidUpdate</code></td>\n<td>component has performed an update</td>\n<td><code>lastProps, lastState, snapshot</code></td>\n</tr>\n<tr>\n<td><code>componentWillUnmount</code></td>\n<td>component is about to be unmounted</td>\n<td></td>\n</tr>\n<tr>\n<td><code>getChildContext</code></td>\n<td>before render method, return value object is combined to sub tree context</td>\n<td></td>\n</tr>\n<tr>\n<td><code>getSnapshotBeforeUpdate</code></td>\n<td>before component updates, return value is sent to componentDidUpdate as 3rd parameter</td>\n<td><code>lastProps, lastState</code></td>\n</tr>\n<tr>\n<td><code>static getDerivedStateFromProps</code></td>\n<td>before render method</td>\n<td><code>nextProps, state</code></td>\n</tr>\n<tr>\n<td><code>componentDidAppear</code></td>\n<td>component has mounted and is ready for animations</td>\n<td><code>domNode</code></td>\n</tr>\n<tr>\n<td><code>componentWillDisappear</code></td>\n<td>component is unmounted before DOM node is removed</td>\n<td><code>domNode, callback</code></td>\n</tr>\n</tbody>\n</table>\n<p dir=\"auto\">componentWillDisappear has special type of argument \"callback\" which needs to be called when component is ready to be removed from the DOM. fe. after animations are finished.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Using functional lifecycle events</h3><a id=\"user-content-using-functional-lifecycle-events\" class=\"anchor\" aria-label=\"Permalink: Using functional lifecycle events\" href=\"#using-functional-lifecycle-events\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Functional lifecycle events must be explicitly assigned via props onto a functional component like shown below:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { render } from 'inferno';\n\nfunction mounted(domNode) {\n // [domNode] will be available for DOM nodes and components (if the component has mounted to the DOM)\n}\n\nfunction FunctionalComponent({ props }) {\n return &lt;div&gt;Hello world&lt;/div&gt;;\n}\n\nrender(\n &lt;FunctionalComponent onComponentDidMount={ mounted } /&gt;,\n document.getElementById(&quot;app&quot;)\n);\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">render</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-en\">mounted</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">domNode</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c\">// [domNode] will be available for DOM nodes and components (if the component has mounted to the DOM)</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-v\">FunctionalComponent</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> props <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span>Hello world<span class=\"pl-c1\">&lt;</span><span class=\"pl-c1\">/</span><span class=\"pl-ent\">div</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">render</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-c1\">&lt;</span><span class=\"pl-ent\">FunctionalComponent</span> <span class=\"pl-c1\">onComponentDidMount</span><span class=\"pl-c1\">=</span><span class=\"pl-kos\">{</span> <span class=\"pl-s1\">mounted</span> <span class=\"pl-kos\">}</span> <span class=\"pl-c1\">/</span><span class=\"pl-c1\">&gt;</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">getElementById</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"app\"</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Please note: class components (ES2015 classes) from <code>inferno</code> <strong>do not</strong> support the same lifecycle events (they have their own lifecycle events that work as methods on the class itself).</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Development vs Production modes</h2><a id=\"user-content-development-vs-production-modes\" class=\"anchor\" aria-label=\"Permalink: Development vs Production modes\" href=\"#development-vs-production-modes\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">By default, Inferno will run in development mode. Development mode provides extra checks and better error messages at the cost of slower performance and larger code to parse.\nWhen using Inferno in a production environment, it is highly recommended that you turn off development mode.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Running Inferno on Node JS</h3><a id=\"user-content-running-inferno-on-node-js\" class=\"anchor\" aria-label=\"Permalink: Running Inferno on Node JS\" href=\"#running-inferno-on-node-js\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Ensure the environment variable <code>process.env.NODE_ENV</code> is set to <code>production</code>.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Application bundling</h2><a id=\"user-content-application-bundling\" class=\"anchor\" aria-label=\"Permalink: Application bundling\" href=\"#application-bundling\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">When building your application bundle, ensure <code>process.env.NODE_ENV</code> is replaced with string<code>\"development\"</code> or <code>\"production\"</code> based on the workflow.\nIt is recommended to use <a href=\"https://github.com/infernojs/ts-plugin-inferno\">ts-plugin-inferno</a> for typescript TSX compilation and <a href=\"https://github.com/infernojs/babel-plugin-inferno\">babel-plugin-infeno</a> for javascript JSX compilation.</p>\n<p dir=\"auto\">When building for development, you may want to use <code>inferno.dev.mjs</code> for v9 or newer and <code>inferno.dev.esm.js</code> for older than v9. That bundle file contains ES6 exports for better tree-shaking support, improved error messages and added validation to help fixing possible issues during development.\nThe file is found from <code>package.json</code> - <code>dev:module</code> entry point and the files are physically located in <code>node_modules/inferno/dist/</code> folder.\nRemember that it is not recommended to use that file in production due to slower performance. For production usage use <code>node_modules/inferno/dist/inferno.mjs</code> -file for v9 or newer and <code>node_modules/inferno/dist/inferno.esm.js</code> -file for older than v9.</p>\n<p dir=\"auto\">Example of <strong>Webpack</strong> configuration:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const path = require('path');\nconst infernoTsx = require('ts-plugin-inferno').default;\n\n... webpack config ...\n\n module: {\n rules: [\n {\n test: /\\.js$/, // Add &quot;jsx&quot; if your application uses `jsx` file extensions\n exclude: /node_modules/,\n use: [{\n loader: 'babel-loader',\n options: {\n plugins: [\n // Compile javascript JSX syntax using inferno's own plugin\n ['babel-plugin-inferno', {imports: true}]\n ]\n }\n }]\n },\n {\n test: /\\.ts+(|x)$/, // Compile ts and tsx extensions\n exclude: /node_modules/,\n use: [{\n loader: 'ts-loader',\n options: {\n getCustomTransformers: () =&gt; ({\n // inferno custom TSX plugin\n after: [infernoTsx()]\n }),\n compilerOptions: {\n /* typescript compiler options */\n }\n }\n }]\n }\n ]\n },\n resolve: {\n extensions: ['.js', '.ts', '.tsx'],\n alias: {\n // This maps import &quot;inferno&quot; to es6 module entry based on workflow\n inferno: path.resolve(__dirname, 'node_modules/inferno/dist', isProduction ? 'index.dev.mjs' : 'index.mjs')\n }\n },\n plugins: [\n new webpack.DefinePlugin({\n 'process.env': {\n 'NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development')\n }\n })\n ]\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-s1\">path</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">require</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'path'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">infernoTsx</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">require</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'ts-plugin-inferno'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">default</span><span class=\"pl-kos\">;</span>\n\n... <span class=\"pl-s1\">webpack</span> <span class=\"pl-s1\">config</span> ...\n\n module: <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">rules</span>: <span class=\"pl-kos\">[</span>\n <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">test</span>: <span class=\"pl-pds\"><span class=\"pl-c1\">/</span>\\.js$<span class=\"pl-c1\">/</span></span><span class=\"pl-kos\">,</span> <span class=\"pl-c\">// Add \"jsx\" if your application uses `jsx` file extensions</span>\n <span class=\"pl-c1\">exclude</span>: <span class=\"pl-pds\"><span class=\"pl-c1\">/</span>node_modules<span class=\"pl-c1\">/</span></span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">use</span>: <span class=\"pl-kos\">[</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">loader</span>: <span class=\"pl-s\">'babel-loader'</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">options</span>: <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">plugins</span>: <span class=\"pl-kos\">[</span>\n <span class=\"pl-c\">// Compile javascript JSX syntax using inferno's own plugin</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s\">'babel-plugin-inferno'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span><span class=\"pl-c1\">imports</span>: <span class=\"pl-c1\">true</span><span class=\"pl-kos\">}</span><span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">test</span>: <span class=\"pl-pds\"><span class=\"pl-c1\">/</span>\\.ts+(|x)$<span class=\"pl-c1\">/</span></span><span class=\"pl-kos\">,</span> <span class=\"pl-c\">// Compile ts and tsx extensions</span>\n <span class=\"pl-c1\">exclude</span>: <span class=\"pl-pds\"><span class=\"pl-c1\">/</span>node_modules<span class=\"pl-c1\">/</span></span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">use</span>: <span class=\"pl-kos\">[</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">loader</span>: <span class=\"pl-s\">'ts-loader'</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">options</span>: <span class=\"pl-kos\">{</span>\n <span class=\"pl-en\">getCustomTransformers</span>: <span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c\">// inferno custom TSX plugin</span>\n <span class=\"pl-c1\">after</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s1\">infernoTsx</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">compilerOptions</span>: <span class=\"pl-kos\">{</span>\n <span class=\"pl-c\">/* typescript compiler options */</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s1\">resolve</span>: <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">extensions</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s\">'.js'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'.ts'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'.tsx'</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">alias</span>: <span class=\"pl-kos\">{</span>\n <span class=\"pl-c\">// This maps import \"inferno\" to es6 module entry based on workflow</span>\n <span class=\"pl-c1\">inferno</span>: <span class=\"pl-s1\">path</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">resolve</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">__dirname</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'node_modules/inferno/dist'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">isProduction</span> ? <span class=\"pl-s\">'index.dev.mjs'</span> : <span class=\"pl-s\">'index.mjs'</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s1\">plugins</span>: <span class=\"pl-kos\">[</span>\n <span class=\"pl-k\">new</span> <span class=\"pl-s1\">webpack</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">DefinePlugin</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-s\">'process.env'</span>: <span class=\"pl-kos\">{</span>\n <span class=\"pl-s\">'NODE_ENV'</span>: <span class=\"pl-c1\">JSON</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">stringify</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">isProduction</span> ? <span class=\"pl-s\">'production'</span> : <span class=\"pl-s\">'development'</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">]</span></pre></div>\n<p dir=\"auto\">Example of <strong>Rollup</strong> configuration:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const path = require('path');\nconst alias = require('@rollup/plugin-alias');\nconst {babel} = require('@rollup/plugin-babel');\nconst replace = require('@rollup/plugin-replace');\nconst typescript = require('rollup-plugin-typescript2');\nconst transformInferno = require('ts-plugin-inferno').default;\n\n... Rollup config ...\n{\n input: /* entry file */,\n plugins: [\n alias({\n resolve: ['.js'],\n entries: [\n // This maps import &quot;inferno&quot; to es6 module entry based on workflow\n {find: 'inferno', replacement: path.resolve(__dirname, 'node_modules/inferno/dist', isProduction ? 'index.dev.mjs' : 'index.mjs')}\n ]\n }),\n typescript({\n include: ['*.ts+(|x)', '**/*.ts+(|x)'],\n transformers: [\n () =&gt; ({\n after: [transformInferno()]\n })\n ],\n tsconfig: 'tsconfig.json',\n tsconfigOverride: {\n /* typescript compiler options */\n }\n }),\n babel({\n babelrc: false,\n sourceMaps: isDeploy,\n plugins: [\n // Compile javascript JSX syntax using inferno's own plugin\n ['babel-plugin-inferno', {imports: true}]\n ],\n babelHelpers: 'bundled'\n })\n ]\n}\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-s1\">path</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">require</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'path'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">alias</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">require</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'@rollup/plugin-alias'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-kos\">{</span>babel<span class=\"pl-kos\">}</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">require</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'@rollup/plugin-babel'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">replace</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">require</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'@rollup/plugin-replace'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">typescript</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">require</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'rollup-plugin-typescript2'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">transformInferno</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">require</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'ts-plugin-inferno'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">default</span><span class=\"pl-kos\">;</span>\n\n... <span class=\"pl-v\">Rollup</span> <span class=\"pl-s1\">config</span> ...\n<span class=\"pl-kos\">{</span>\n input: <span class=\"pl-c\">/* entry file */</span><span class=\"pl-kos\">,</span>\n plugins: <span class=\"pl-kos\">[</span>\n <span class=\"pl-s1\">alias</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">resolve</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s\">'.js'</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">entries</span>: <span class=\"pl-kos\">[</span>\n <span class=\"pl-c\">// This maps import \"inferno\" to es6 module entry based on workflow</span>\n <span class=\"pl-kos\">{</span><span class=\"pl-c1\">find</span>: <span class=\"pl-s\">'inferno'</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">replacement</span>: <span class=\"pl-s1\">path</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">resolve</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">__dirname</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'node_modules/inferno/dist'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">isProduction</span> ? <span class=\"pl-s\">'index.dev.mjs'</span> : <span class=\"pl-s\">'index.mjs'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-s1\">typescript</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">include</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s\">'*.ts+(|x)'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'**/*.ts+(|x)'</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">transformers</span>: <span class=\"pl-kos\">[</span>\n <span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">after</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s1\">transformInferno</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">tsconfig</span>: <span class=\"pl-s\">'tsconfig.json'</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">tsconfigOverride</span>: <span class=\"pl-kos\">{</span>\n <span class=\"pl-c\">/* typescript compiler options */</span>\n <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">babel</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">babelrc</span>: <span class=\"pl-c1\">false</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">sourceMaps</span>: <span class=\"pl-s1\">isDeploy</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">plugins</span>: <span class=\"pl-kos\">[</span>\n <span class=\"pl-c\">// Compile javascript JSX syntax using inferno's own plugin</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-s\">'babel-plugin-inferno'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span><span class=\"pl-c1\">imports</span>: <span class=\"pl-c1\">true</span><span class=\"pl-kos\">}</span><span class=\"pl-kos\">]</span>\n <span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">babelHelpers</span>: <span class=\"pl-s\">'bundled'</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">}</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Custom namespaces</h3><a id=\"user-content-custom-namespaces\" class=\"anchor\" aria-label=\"Permalink: Custom namespaces\" href=\"#custom-namespaces\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Inferno always wants to deliver great performance. In order to do so, it has to make intelligent assumptions about the state of the DOM and the elements available to mutate. Custom namespaces conflict with this idea and change the schema of how different elements and attributes might work, so Inferno makes no attempt to support namespaces. Instead, SVG namespaces are automatically applied to elements and attributes based on their <code>tag name</code>.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Development</h2><a id=\"user-content-development\" class=\"anchor\" aria-label=\"Permalink: Development\" href=\"#development\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">If you want to contribute code, fork this project and submit a PR from your fork. To run browser tests you need to build the repos. A complete rebuild of the repos can take &gt;5 mins.</p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"$ git clone [email protected]:infernojs/inferno.git\n$ cd inferno &amp;&amp; npm i\n$ npm run test:node\n$ npm run build\n$ npm run test:browser\"><pre>$ git clone [email protected]:infernojs/inferno.git\n$ <span class=\"pl-c1\">cd</span> inferno <span class=\"pl-k\">&amp;&amp;</span> npm i\n$ npm run test:node\n$ npm run build\n$ npm run test:browser</pre></div>\n<p dir=\"auto\">If you only want to run the browser tests when coding, use the following to reduce turnaround by 50-80%:</p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"$ npm run quick-test:browser # Compiles all packages and runs browser tests\n$ npm run quick-test:browser-inferno # Only compiles the inferno package and runs browser tests\n$ npm run quick-test:browser-debug # Compiles all packages and runs browser tests with &quot;debug&quot;\"><pre>$ npm run quick-test:browser <span class=\"pl-c\"><span class=\"pl-c\">#</span> Compiles all packages and runs browser tests</span>\n$ npm run quick-test:browser-inferno <span class=\"pl-c\"><span class=\"pl-c\">#</span> Only compiles the inferno package and runs browser tests</span>\n$ npm run quick-test:browser-debug <span class=\"pl-c\"><span class=\"pl-c\">#</span> Compiles all packages and runs browser tests with \"debug\"</span></pre></div>\n<div class=\"markdown-heading\" dir=\"auto\"><h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Community</h2><a id=\"user-content-community\" class=\"anchor\" aria-label=\"Permalink: Community\" href=\"#community\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">There is an InfernoJS Discord. You can join via <a href=\"https://discord.gg/SUKuhgaBpF\" rel=\"nofollow\">https://discord.gg/SUKuhgaBpF</a>.</p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Contributors</h3><a id=\"user-content-contributors\" class=\"anchor\" aria-label=\"Permalink: Contributors\" href=\"#contributors\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">This project exists thanks to all the people who contribute. [<a href=\"/infernojs/inferno/blob/master/CONTRIBUTING.md\">Contribute</a>].\n<a href=\"https://github.com/infernojs/inferno/graphs/contributors\"><img src=\"https://camo.githubusercontent.com/8f054dbbc2edf4ebf4959c1ad871dd09bd39cc68300d3c733bc7a8e79baf7348/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f636f6e7472696275746f72732e7376673f77696474683d383930\" data-canonical-src=\"https://opencollective.com/inferno/contributors.svg?width=890\" style=\"max-width: 100%;\"></a></p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Backers</h3><a id=\"user-content-backers\" class=\"anchor\" aria-label=\"Permalink: Backers\" href=\"#backers\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Thank you to all our backers! 🙏 [<a href=\"https://opencollective.com/inferno#backer\" rel=\"nofollow\">Become a backer</a>]</p>\n<p dir=\"auto\"><a href=\"https://opencollective.com/inferno#backers\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/09a09ccf63cf44941f9e4118143e3d844f0737b2799065622ca7b55fb17d6f75/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f6261636b6572732e7376673f77696474683d383930\" data-canonical-src=\"https://opencollective.com/inferno/backers.svg?width=890\" style=\"max-width: 100%;\"></a></p>\n<div class=\"markdown-heading\" dir=\"auto\"><h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Sponsors</h3><a id=\"user-content-sponsors\" class=\"anchor\" aria-label=\"Permalink: Sponsors\" href=\"#sponsors\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a></div>\n<p dir=\"auto\">Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [<a href=\"https://opencollective.com/inferno#sponsor\" rel=\"nofollow\">Become a sponsor</a>]</p>\n<p dir=\"auto\"><a href=\"https://opencollective.com/inferno/sponsor/0/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/e68381334661963431b13d69ef2db936584f7ff702a8513e84222ab803934c1b/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f302f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/0/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/1/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/f89725d34de62fdd4f47e58bf17c8c062a037d1575e9ac87a88c6734fdc06eb1/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f312f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/1/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/2/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/bdcf8b5e326a4e9c009d986dee38be4ee0b76a8ec804896bfafafd236c1f6c79/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f322f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/2/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/3/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/7d57f03ef2e9bf5138a2a1f3dfa763f8d9e09c37e18be82706624bf29cd68b36/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f332f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/3/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/4/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/221df17979a35a043b9999aee22d1bc16dc9d3d7e333240490787ee745700d0d/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f342f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/4/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/5/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/73e44404789bec33e244ea0b3671848b96714e8a7f8312fcc12766824e74b003/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f352f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/5/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/6/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/f8be188e1a69bc56f2ad36b22a03d7504407aa5cc53fbe4c09de03f91196a4fb/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f362f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/6/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/7/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/f3ffbaa0339bf0a84718d1d6f51645e12e5e2014f0aa92dd6d76ad5ca476fa97/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f372f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/7/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/8/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/4cfd90de584f1cebf23ef521070069efcb3c1d5bad66c5ed8d550f81348be965/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f382f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/8/avatar.svg\" style=\"max-width: 100%;\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/9/website\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/296fbf91abb60c36ad686671d3b1b85198b6eec4cebfab0afce7e14df8d3c40a/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f696e6665726e6f2f73706f6e736f722f392f6176617461722e737667\" data-canonical-src=\"https://opencollective.com/inferno/sponsor/9/avatar.svg\" style=\"max-width: 100%;\"></a></p>\n</article>",
"loaded": true,
"timedOut": false,
"errorMessage": null,
"headerInfo": {
"toc": [
{
"level": 2,
"text": "Description",
"anchor": "description",
"htmlText": "Description"
},
{
"level": 2,
"text": "Features",
"anchor": "features",
"htmlText": "Features"
},
{
"level": 2,
"text": "Runtime requirements",
"anchor": "runtime-requirements",
"htmlText": "Runtime requirements"
},
{
"level": 2,
"text": "Browser support",
"anchor": "browser-support",
"htmlText": "Browser support"
},
{
"level": 2,
"text": "Migration guides",
"anchor": "migration-guides",
"htmlText": "Migration guides"
},
{
"level": 2,
"text": "Benchmarks",
"anchor": "benchmarks",
"htmlText": "Benchmarks"
},
{
"level": 2,
"text": "Code Example",
"anchor": "code-example",
"htmlText": "Code Example"
},
{
"level": 3,
"text": "Tear down",
"anchor": "tear-down",
"htmlText": "Tear down"
},
{
"level": 3,
"text": "More Examples",
"anchor": "more-examples",
"htmlText": "More Examples"
},
{
"level": 2,
"text": "Getting Started",
"anchor": "getting-started",
"htmlText": "Getting Started"
},
{
"level": 3,
"text": "Creating Virtual DOM",
"anchor": "creating-virtual-dom",
"htmlText": "Creating Virtual DOM"
},
{
"level": 4,
"text": "JSX:",
"anchor": "jsx",
"htmlText": "JSX:"
},
{
"level": 4,
"text": "Hyperscript:",
"anchor": "hyperscript",
"htmlText": "Hyperscript:"
},
{
"level": 4,
"text": "createElement:",
"anchor": "createelement",
"htmlText": "createElement:"
},
{
"level": 3,
"text": "Compatibility with existing React apps",
"anchor": "compatibility-with-existing-react-apps",
"htmlText": "Compatibility with existing React apps"
},
{
"level": 2,
"text": "Third-party state libraries",
"anchor": "third-party-state-libraries",
"htmlText": "Third-party state libraries"
},
{
"level": 2,
"text": "JSX",
"anchor": "jsx-1",
"htmlText": "JSX"
},
{
"level": 2,
"text": "Differences from React",
"anchor": "differences-from-react",
"htmlText": "Differences from React"
},
{
"level": 2,
"text": "Differences from Preact",
"anchor": "differences-from-preact",
"htmlText": "Differences from Preact"
},
{
"level": 2,
"text": "Event System",
"anchor": "event-system",
"htmlText": "Event System"
},
{
"level": 3,
"text": "linkEvent (package: inferno)",
"anchor": "linkevent-package-inferno",
"htmlText": "linkEvent (package: inferno)"
},
{
"level": 2,
"text": "Controlled Components",
"anchor": "controlled-components",
"htmlText": "Controlled Components"
},
{
"level": 2,
"text": "Inferno Top-Level API",
"anchor": "inferno-top-level-api",
"htmlText": "Inferno Top-Level API"
},
{
"level": 3,
"text": "render (package: inferno)",
"anchor": "render-package-inferno",
"htmlText": "render (package: inferno)"
},
{
"level": 3,
"text": "createRenderer (package: inferno)",
"anchor": "createrenderer-package-inferno",
"htmlText": "createRenderer (package: inferno)"
},
{
"level": 3,
"text": "createElement (package: inferno-create-element)",
"anchor": "createelement-package-inferno-create-element",
"htmlText": "createElement (package: inferno-create-element)"
},
{
"level": 3,
"text": "Component (package: inferno)",
"anchor": "component-package-inferno",
"htmlText": "Component (package: inferno)"
},
{
"level": 3,
"text": "createVNode (package: inferno)",
"anchor": "createvnode-package-inferno",
"htmlText": "createVNode (package: inferno)"
},
{
"level": 3,
"text": "createComponentVNode (package: 'inferno')",
"anchor": "createcomponentvnode-package-inferno",
"htmlText": "createComponentVNode (package: 'inferno')"
},
{
"level": 3,
"text": "createTextVNode (package: 'inferno')",
"anchor": "createtextvnode-package-inferno",
"htmlText": "createTextVNode (package: 'inferno')"
},
{
"level": 3,
"text": "cloneVNode (package: inferno-clone-vnode)",
"anchor": "clonevnode-package-inferno-clone-vnode",
"htmlText": "cloneVNode (package: inferno-clone-vnode)"
},
{
"level": 3,
"text": "createPortal (package: 'inferno')",
"anchor": "createportal-package-inferno",
"htmlText": "createPortal (package: 'inferno')"
},
{
"level": 3,
"text": "createRef (package: inferno)",
"anchor": "createref-package-inferno",
"htmlText": "createRef (package: inferno)"
},
{
"level": 3,
"text": "createFragment (package: inferno)",
"anchor":