Comparing React JS and Solid JS in Syntax

Comparing React JS and Solid JS in Syntax

React is one framework that gets me a job as Engineer and my first "language" when it comes to frontend framework, so I will be comparing it to react.

ยท

4 min read

Many new front-end web frameworks have been released in the last few years. Svelte, Preact, Angular, Ember, and Remix (although it is not all front-end frameworks). Lately, Solid Js has been discussed, and I decided to look at it.

There are many articles regarding how excellent Solid js is and how blazingly efficient it is. But this time, I will focus on syntax. I'm a big fan of React js; react is one framework that gets me a job as Engineer and my first "language" when it comes to frontend framework, so I will be comparing it to react.

State

Let's start with the state. The easiest way to show the state's power is by building a counter. In React, I would be writing it like this.

import React from 'react';

export function App(props) {
  const [count, setCount] = React.useState(0)

  return (
    <div>
      <div>Count: {count}</div>
      <button onClick={() => setCount(count + 1)}>add</button>
    </div>
  )
}

in Solid, it will be

import { render } from "solid-js/web";
import { createSignal } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(0);

  return (
    <div>
      <div>{count()}</div>
      <button type="button" onClick={() => setCount(count() + 1)}>
        add
      </button>
    </div>
  )
}

Beside Solid called it Signal. It is almost the same. The only difference is when referencing state, Solid needs to call it (count()) while React does not (count).

Props

As for props, it is almost the same. We hand over the value to the child element, and the child element reads it. Because Solid's reactivity occurs on property access on Prop and State objects. Referencing them outside of a binding or reactive computation will not be tracked. Use built-in utilities like mergeProps and splitProps to prevent that.

Effect

Next, I will try to replicate React's useEffect on Solid. Let's say we want to log our count when the state/signal is updated.

import React from 'react';

export function App(props) {
  const [count, setCount] = React.useState(0)

  React.useEffect(
    () => {
      console.log(`Count: ${count}`)
    },
    [count]
  )

  return (
    <div>
      <div>Count: {count}</div>
      <button onClick={() => setCount(count + 1)}>add</button>
    </div>
  )
}

In Solid, I would write it like this.

function Counter() {
  const [count, setCount] = createSignal(0);
  createEffect(() => {
    console.log(`Count: ${count()}`)
  })

  return (
    <div>
      <div>{count()}</div>
      <button type="button" onClick={() => setCount(count() + 1)}>
        add
      </button>
    </div>
  )
}

Pretty similar. With Solid, we don't need to fill out dependencies manually. As for lifecycle, same as React, we can use createEffect without any dependencies (or use onMount), and for the clean up, we can use the onCleanup function. As opposed to React, we use return.

Memo(s)

Unlike React, Solid's components only mount once and don't rerender. Therefore, Solid doesn't need a reference identity function like useCallback. But Solid has a createMemo function for caching purposes. It makes read-only variables that only calculate when dependency (in most cases, prop and signal). In React, we would write it like this.

export function App(props) {
  const [count, setCount] = React.useState(0)

  const calcValue = React.useMemo(
    () => count**100/5**200,
    [count]
  )

  return (
    <div>
      <div>Count: {count}</div>
      <button onClick={() => setCount(count + 1)}>add</button>
      <div>Calc: {calcValue}</div>
    </div>
  )
}

In Solid, we would write it like this.

function Counter() {
  const [count, setCount] = createSignal(0);
  const calcValue = createMemo(() => count()**100/5**200)

  return (
    <div>
      <div>{count()}</div>
      <button type="button" onClick={() => setCount(count() + 1)}>
        add
      </button>
      <div>Calc: {calcValue()}</div>
    </div>
  )
}

Again, the only difference is with Solid, we don't need to declare dependencies, and when referencing it, we call it (. calcValue())

Context

When building a large application, chances are we will need some kind of global state. In React, we have of it; the most popular is Redux. But this time, we will take into built-in function Context. In React, we would write it like this.

const CountContext = React.createContext({
  count: 0,
  setCount: () => void 0
});

export function App(props) {
  const [count, setCount] = React.useState(0)

  return (
    <CountContext.Provider value={{
      count,
      setCount
    }}>
      <Counter />
    </CountContext.Provider>
  )
}

function Counter() {
  const countContext = React.useContext(CountContext)

  return (<>
    <div>Count: {countContext.count}</div>
    <button onClick={() => countContext.setCount(count => count + 1)}>add</button>
  </>)
}

In Solid, we could write like this.

const CountContext = createContext({
  count: 0,
  setCount: () => void 0
})

function App() {
  const [count, setCount] = createSignal(0)
  const store = {
    count,
    setCount
  }

  return (
    <CountContext.Provider value={store}>
      <Counter />
    </CountContext.Provider>
  );
}

function Counter() {
  const countContext = useContext(CountContext)

  return (<>
    <div>Count: {countContext.count()}</div>
    <button onClick={() => countContext.setCount(count => count + 1)}>add</button>
  </>)
}

There is not much to comment on here; we can write it the same way.

Ending

I'm surprised at how similar React and Solid are and excited about Solid in the future. What do you think

Did you find this article valuable?

Support Alvin Endratno by becoming a sponsor. Any amount is appreciated!

ย