Security News
Supply Chain Attack Detected in @solana/web3.js Library
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
An extremely fast, React-like JavaScript library for building modern user interfaces
Inferno is a fast, lightweight, and highly performant JavaScript library for building modern user interfaces. It is similar to React in terms of API and functionality but is optimized for speed and performance.
Component Creation
Inferno allows you to create components using a class-based approach similar to React. This example demonstrates how to create a simple component that renders a 'Hello, Inferno!' message.
const { Component } = require('inferno');
class MyComponent extends Component {
render() {
return <div>Hello, Inferno!</div>;
}
}
module.exports = MyComponent;
JSX Support
Inferno supports JSX syntax, which allows you to write HTML-like code within your JavaScript. This example shows how to use JSX to create a simple component.
const Inferno = require('inferno');
const MyComponent = () => (
<div>
<h1>Welcome to Inferno</h1>
<p>This is a JSX example.</p>
</div>
);
module.exports = MyComponent;
State Management
Inferno provides state management capabilities similar to React. This example demonstrates a simple counter component that increments the count when a button is clicked.
const { Component } = require('inferno');
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
module.exports = Counter;
Lifecycle Methods
Inferno supports lifecycle methods that allow you to hook into different stages of a component's lifecycle. This example demonstrates the use of `componentDidMount` and `componentWillUnmount` lifecycle methods.
const { Component } = require('inferno');
class LifecycleDemo extends Component {
componentDidMount() {
console.log('Component mounted');
}
componentWillUnmount() {
console.log('Component will unmount');
}
render() {
return <div>Check the console for lifecycle logs.</div>;
}
}
module.exports = LifecycleDemo;
React is a popular JavaScript library for building user interfaces, developed by Facebook. It offers a similar component-based architecture and lifecycle methods as Inferno but is more widely adopted and has a larger ecosystem.
Preact is a fast 3kB alternative to React with the same modern API. It is similar to Inferno in terms of performance and size but has a slightly different approach to handling components and state.
Vue.js is a progressive JavaScript framework for building user interfaces. It offers a more opinionated approach compared to Inferno and includes features like directives and a built-in state management system.
Inferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server.
The main objective of the Inferno 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:
createVNode
calls, instead of createElement
linkEvent
feature removes the need to use arrow functions or binding event callbacksinferno-server
createPortal
- APISince 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 natively supports the browsers listed below.
List of breaking changes can be found from here
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 to predefine children shape compile time.
Then we create text vNode using createTextVNode
.
import { createTextVNode, render, Component } from 'inferno';
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
}
render() {
return (
<div>
<h1>Header!</h1>
<span $HasVNodeChildren>{createTextVNode('Counter is at: ' + this.state.counter)}</span>
</div>
);
}
}
render(
<MyComponent />,
document.getElementById("app")
);
If you have built something using Inferno you can add them here:
The best way to get started with Inferno is by using Create Inferno App.
Alternatively, you can use the Inferno Boilerplate for a very simple setup. For a more advanced example demonstrating how Inferno might be used, we recommend trying out Inferno Starter Project by nightwolfz. For using Inferno to build a mobile app, try Inferno Mobile Starter Project by Rudy-Zidan.
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
npm install --save-dev babel-plugin-inferno
npm install --save inferno-hyperscript
npm install --save inferno-create-element
npm install --save-dev inferno-compat
Note: Make sure you read more about inferno-compat
before using it.
Inferno now has bindings available for some of the major state management libraries out there:
inferno-redux
inferno-mobx
cerebral-view-inferno
Inferno has its own JSX Babel plugin.
~8kb
vs 45kb
gzip. This means Inferno is faster to transfer over the network but more importantly, it is much faster to parse – this makes a big impact on mobile.1.0
. No other React-like library gets close to this performance gain over React.onClick
).inferno-compat
. We don't recommend using them since they are the source of many memory leaks and performance issues in real-world apps. Stick with function callback refs instead.render
on the main core package, rather than have an InfernoDOM
package like React does. We used to do it that way, but we found people simply didn't like it given we don't support native. Furthermore, by not splitting them, we improved performance and bundle sizes.inferno-devtools
.~8kb
vs 3kb
gzip. This means that Preact should parse faster than Inferno – if only slightly.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.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
onMouseMove
onMouseDown
onMouseUp
onSubmit
onKeyPress
onKeyDown
onKeyUp
onInput
onChange
onFocusIn
onFocusOut
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.
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".
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() {
...
}
}
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;
}
};
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
VNode
s 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 { cloneVNode, createVNode, render } from 'inferno';
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, cloneVNode } from 'inferno';
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!
hydrate
(package: inferno
)import { hydrate } from 'inferno';
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-compat
)This feature has been moved from inferno to inferno-compat in v4 forward. 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.
VNodeFlags:
VNodeFlags.HtmlElement
VNodeFlags.ComponentUnknown
VNodeFlags.ComponentClass
VNodeFlags.ComponentFunction
VNodeFlags.Text
VNodeFlags.SvgElement
VNodeFlags.InputElement
VNodeFlags.TextareaElement
VNodeFlags.SelectElement
VNodeFlags.Void
VNodeFlags.Portal
VNodeFlags.ReCreate
(JSX $ReCreate) always re-creates the vNodeVNodeFlags Masks:
VNodeFlags.FormElement
- Is from elementVNodeFlags.Element
- Is vNode elementVNodeFlags.Component
- Is vNode ComponentVNodeFlags.VNodeShape
- mask for defining typeChildFlags
ChildFlags.UnknownChildren
needs NormalizationChildFlags.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 Masks
ChildFlags.MultipleChildren
Is ArrayrenderToString
(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.
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 updated | lastProps, nextProps |
onComponentWillUpdate | a functional component is about to perform an update | lastProps, nextProps |
onComponentDidUpdate | a functional component has performed an updated | lastProps, nextProps |
onComponentWillUnmount | a functional component is about to be unmounted | domNode |
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).
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.
Ensure the environment variable process.env.NODE_ENV
is set to production
.
When running Inferno on the browser using Webpack or Rollup, a replacement will need to occur during your build.
Use the following configuration in your Webpack build for production build:
...
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
]
When you are building for development, you may want to use inferno.dev.mjs
("dev:module": "dist/index.dev.mjs",) file.
That build version has extra level of validation for development purposes. You can use it by adding following code to your webpack config.
...
resolve: {
/* When doing development workflow we want to make sure webpack picks up development build of inferno */
alias: {
inferno: __dirname + "/node_modules/inferno/dist/index.dev.mjs"
}
}
Use the following configuration in your Rollup build:
const replace = require('rollup-plugin-replace');
...
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
})
]
When you are building for development, you may want to use inferno.dev.mjs
("dev:module": "dist/index.dev.mjs",) file.
That build version has extra level of validation for development purposes. You can use it by adding following code to your rollup config.
const alias = require('rollup-plugin-alias');
...
plugins: {
/* When doing development workflow we want to make sure webpack picks up development build of inferno */
alias: {
'inferno': __dirname + '/node_modules/inferno/dist/index.dev.mjs'
}
}
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
.
There is an Inferno Slack. You can join via inferno-slack.herokuapp.com.
This project exists thanks to all the people who contribute. [Contribute].
Thank you to all our backers! 🙏 [Become a backer]
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
FAQs
An extremely fast, React-like JavaScript library for building modern user interfaces
We found that inferno demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.