DEV Community

Cover image for Preact vs. React
Jollen Moyani for Syncfusion, Inc.

Posted on • Originally published at syncfusion.com on

Preact vs. React

Front-end development has evolved tremendously over time. The constant need for large-scale web app development at a faster pace has led to the inception of many JavaScript frameworks.

Of the many, React has become one of the most popular with time. It has large community adoption, easy-to-use APIs, and is developer-friendly, especially for newbies. According to the StackOverflowdeveloper survey, it is the most popular framework for web app development.

Despite its popularity, React is still considered a slow framework because of its virtual DOM and the large file size of its core implementation, especially for large applications.

These drawbacks of React inspired a new framework named Preact, which is custom-tailored for certain types of applications as an alternative to React.

Preact is a 3KB but uses the same cutting-edge API and has the same support for ECMAScript. Its small size is due to the fact that it was created to function in a browser with the DOM, incorporating the virtual DOM like many frameworks. Additionally, it beats other JavaScript frameworks in terms of speed.

The popularity of Preact is reflected by the fact that it has 33,100 stars on GitHub and 1,799,020 weekly downloads on npm at the time of writing this article.

Where does React excel?

React is the best choice when we have to build complex and highly scalable apps, especially SPAs. It has kept functional programming at the core, still infusing declarative and component-based styles, making it easier to distribute and develop applications in a large team.

The virtual DOM ensures high speed and minimum change re-renders of components when there is an update in the application.

React also provides effective server-side rendering, making it the ideal JavaScript framework for building apps that are simple to optimize for search engines.

Having extensive community support is the cherry on top.

Where does Preact excel?

If performance, speed, and size of the application are important factors to you, Preact is the ideal option. It is mainly utilized to create advanced web apps. For instance, Uber moved to Preact in production to make its PWA lightweight and powerful.

Aside from this, Preact is a tiny library, and it is built on top of React, so there is not much additional learning required. It is simple to use and can be used with the current React package with some aliasing, i.e., using preact/compat, due to its compatibility and likeness to React.

Differences between Preact and React

Preact is not the reimplementation of React. Rather, it is a booster dose that aims to fix certain bottlenecks that hamper performance.

preact/compat adds a thin layer on Preact in an effort to make Preact completely compatible with React.

Primary Difference

Events

The primary difference between React and Preact is that React uses synthetic events, which are wrapped around the actual events that React has added to make all the events work seamlessly across all browsers.

Preact has discarded these for their performance and code-size issues.

It registers event handlers using the browser’s standard addEventListener. Event nomenclature and behavior are identical to those of simple JavaScript/DOM.

With a few minor exceptions, the standard browser events function similarly to how they operate in React:

  • Events don’t bubble up through components.
  • Form inputs support native events. For example, we can use oninput rather than React’s onChange.
  • Similarly, rather than using React’s onDoubleClick _ , _ the standard onDblClick should be used.
  • In Preact, for “input type = search,” always use onsearch to listen to the events. In IE11, the clear icon doesn’t’ fire onInput.

Preact adheres more closely to the DOM specification, custom events are supported with case-sensitive names, and custom elements are handled similarly to standard elements (as they are in the DOM).

If you want to use the existing APIs of React in Preact, you can do so with the help of preact/compat.

Hooks

Hooks are not part of the core in Preact. They have been separated out to keep the main bundle small and thus need to be imported separately.

We can import Hooks either from preact/hooks or preact/compat.

import { useState } from 'preact/hooks';

const App = () => {
  const [number, setNumber] = useState(0);
  const increment = () => setNumber(count + 1);
  // callback can be passed to the setter
  const decrement = () => setNumber((currentNumber) => currentNumber - 1);

  return (
    <div>
      <p>Number: {Number}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  )
};

Enter fullscreen mode Exit fullscreen mode

Rendering

Preact is one of the quickest virtual DOM libraries available thanks to its small size as well as its simple and reliable implementation of the diff.

Secondary differences

Native support for ES modules

Preact was one of the earliest frameworks to support ES modules because it was designed with the module system in mind. We can load ES modules directly in browsers using the import keyword without going via a bundler first.

<script type="module">
  import { h, Component, render } from 'https://unpkg.com/preact?module';
  import htm from 'https://unpkg.com/htm?module';

  // initialize htm with Preact
  const html = htm.bind(h);

  function App (props) {
    return html`<h1>Hello ${props.name}!</h1>`;
  }

  // render App with bypassing prop name=”world”
  render(html`<${App} name="World" />`, document.body);
</script>

Enter fullscreen mode Exit fullscreen mode

render() method has arguments

Preact has conveniently given this.props and this.state to the class component’s render() method.

In React and Preact, using preact/compat.

class App extends Component {
  state = { count: 1 };

  render() {
    return <div>Name: {this.props.name}, Count: {this.state.count}</div>;
  }
}

Enter fullscreen mode Exit fullscreen mode

In Preact without preact/compat.

class App extends Component {
  state = { count: 1 };

  render({ name }, { count }) {
    return <div>Name: {name}, Count: {count}</div>;
  }
}

Enter fullscreen mode Exit fullscreen mode

Native HTML attribute/property names

Preact strives to resemble the DOM specification that is accepted by all significant browsers. Preact internally determines whether each prop should be set as an HTML attribute or a property when applying props to an element. This not only allows complex properties to be put on custom elements, but also allows attribute names like the class in JSX.

//Preact
<div class="foo" />

//React
<div className="foo" />

Enter fullscreen mode Exit fullscreen mode

SVG inside JSX

SVG are the JavaScript of the HTML tags when it comes to properties and attributes.

A few properties and their attributes are camelCased such as the clipPathUnits on a clipPath element. Others are kebab-cased, such as clip-path on many SVG elements), while those inherited from the DOM, such as oninput, are all lowercase.

Preact supports the SVG natively. You can copy any SVG snippet and have it go as expected. This makes developers’ life easy, as they can directly pick things from mockups rather than converting attributes or properties to camel case.

SVG in React

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
  <circle fill="none" strokeWidth="2" strokeLinejoin="round" cx="24" cy="24" r="20" />
</svg>
Enter fullscreen mode Exit fullscreen mode

SVG in Preact

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
  <circle fill="none" stroke-width="2" stroke-linejoin="round" cx="24" cy="24" r="20" />
</svg>

Enter fullscreen mode Exit fullscreen mode

Form events

We no longer have to use the onChange event on form elements. You can use the native input, and it will work the same.

React

<input onChange={e => console.log(e.target.value)} />
Enter fullscreen mode Exit fullscreen mode

Preact

<input onInput={e => console.log(e.target.value)} />
Enter fullscreen mode Exit fullscreen mode

The majority of onChange events are internally transformed to onInput when using preact/compat to mimic React’s behavior. This is one of the techniques to make sure the React ecosystem is as compatible as possible.

JSX constructor

Simply put, JSX is the JavaScript syntactic extension that transforms JSX into nested functional calls.

Preact promotes the original universal community standard that the hyperscript project popularized in JavaScript and makes use of nested function calls to construct tree structures.

JSX

<a href=/>
  <span>Home</span>
</a>
Enter fullscreen mode Exit fullscreen mode

React output

React.createElement(
  'a',
  { href:'/' },
  React.createElement('span', null, 'Home')
);
Enter fullscreen mode Exit fullscreen mode

Preact output

h(
  'a',
  { href:'/' },
  h('span', null, 'Home')
);

Enter fullscreen mode Exit fullscreen mode

Children API

In React, for interacting with the value of props.children , there is a specific collection of methods called the Children API. Preact normally does not need this, so they advise using the built-in array methods.

In Preact, props.children can be a virtual DOM node, a value that is empty, such as null, or an array of virtual DOM nodes. Since children can be used or returned in their current state, the first two scenarios are the most straightforward and frequent.

React

function App(props) {
  return <Element content={Children.only(props.children)} />
}

Enter fullscreen mode Exit fullscreen mode

Preact

// Preact: use props.children directly:
function App(props) {
  return <Element content={props.children} />
}

Enter fullscreen mode Exit fullscreen mode

If you want to iterate over the children received, you can use the toChildArray() method. It accepts any props.children value and return a flattened and normalized array of virtual DOM nodes.

React

function App(props) {
  const cols = Children.count(props.children);
  return <div data-columns={cols}>{props.children}</div>
}
Enter fullscreen mode Exit fullscreen mode

Preact

function App(props) {
  const cols = toChildArray(props.children).length;
  return <div data-columns={cols}>{props.children}</div>
}
Enter fullscreen mode Exit fullscreen mode

Integrating an existing React app with Preact

There are also some specialized components in Preact designed for special cases.

In order to use them, we have to set up the preact/compat.

The simplest way is to use the alias and partly migrate the features of React with Preact while still continuing to use the existing libraries of React.

To set any package in the webpack as the alias, update or add the resolve.alias section in your webpack config.

"resolve": { 
    "alias": { 
      "react": "preact/compat",
      "react-dom/test-utils": "preact/test-utils",
      // should always be below the test-utils
      "react-dom": "preact/compat",     
      "react/jsx-runtime": "preact/jsx-runtime"
    },
  }
Enter fullscreen mode Exit fullscreen mode

Our setup is done, and now we can use these extra features of Preact in the existing application:

PureComponent: Component rerenders or updates only when the props or state have changed.

import { render } from 'preact';
import { PureComponent } from 'preact/compat';

class App extends PureComponent {
  render(props) {
    console.log("called")
    return <div />
  }
};

const dom = document.getElementById('root');
render(<App name="syncfusion" />, dom);
// Logs: "called"

// second time, doesn't log anything
render(<App name="syncfusion" />, dom);
Enter fullscreen mode Exit fullscreen mode

memo: Similar to PureComponent, but memo lets you use a custom comparison function for deciding the updates conditionally.

import { memo } from 'preact/compat';

function App(props) {
  return <div>Hello {props.name}</div>
}

// normal memoization
const Memoed = memo(App);

// memoizing with custom comparison function
const Memoed2 = memo(App, (prevProps, nextProps) => {
  // re-render when `name' changes
  return prevProps.name === nextProps.name;
});
Enter fullscreen mode Exit fullscreen mode

forwardRef: Passes the reference to the child components.

import { createRef, render } from 'preact';
import { forwardRef } from 'preact/compat';

const App = forwardRef((props, ref) => {
  return <div ref={ref}>Hello world</div>;
})

// `ref` will reference to the div child rather than the `App`
const ref = createRef();
render(<App ref={ref} />, dom);
Enter fullscreen mode Exit fullscreen mode

Portals: Allows us to render components in different DOM elements.

<html>
  <body>
    <!-- app will render here -->
    <div id="app"></div>
    <!-- modal will render here -->
    <div id="modals"></div>
  </body>
</html>

import { createPortal } from 'preact/compat';
import MyModal from './MyModal';

function App() {
  const container = document.getElementById('modals');
  return (
    <div>
      I'm app
      {/*modal will render in its container outside the app*/}
      {createPortal(<MyModal />, container)}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Creating a fresh Preact app

Preact also has a built-in CLI and we can use it to scaffold a new project, similar to the create-react-app.

Install CLI

npm install -g preact-cli
Enter fullscreen mode Exit fullscreen mode

Create new project

preact create default my-project
Enter fullscreen mode Exit fullscreen mode

Here, the default keyword refers to the one you would like to use for your project.

Popular available choices are:

  • Simple: Blank setup with Vanilla JS.
  • TypeScript: Setup using TypeScript.
  • Material: Setup using Material design.
  • Netlify: Setup using Netlify CMS template.
  • Widget: To be embeddable as a widget in another web app.

Advantages of choosing Preact over React

  • Tiny and speedy : Preact is the best framework for creating high-performing, lightweight apps because it is only 3.5 KB in size and renders swiftly using the optimized diff algorithm.
  • Integrable: It supports the same ECMAScript and is extremely compatible with the React APIs, making it effective enough to integrate into an active React project for improved performance.
  • Easy to learn : The learning curve is easy because it is well-documented, and the APIs are similar to React.
  • Built-in CLI : Preact features a strong CLI that enables developers to create a PWA in a matter of seconds without having to set up Babel or WebPack.

Conclusion

I hope you now have a clear idea of differences between Preact and React. React is a popular JavaScript library among web developers, while Preact is an enhanced version of React that makes applications lighter and faster.

The Syncfusion Essential Studio for React suite offers over 70 high-performance, lightweight, modular, and responsive UI components in a single package. It’s the only suite you’ll ever need to construct a complete app.

If you have questions, contact us through our support forum, support portal, or feedback portal. We are always happy to assist you!

Related blogs

Top comments (0)