Solid.js vs Marko Comparison

Reactivity

Reactivity is a core feature in both Solid.js and Marko, allowing developers to build dynamic and responsive applications. Let’s explore how each framework handles state declaration, updates, and computed properties.

Declare state

Solid.js

Name.jsx

import { createSignal } from "solid-js";

export default function Name() {
  const [name] = createSignal("John");

  return <h1>Hello {name()}</h1>;
}

In Solid.js, state is managed using signals, which are functions that return the current state and can be called to update it.

Marko

Name.marko

<let/name = "John"/>
<h1>Hello ${name}</h1>

In Marko, state is declared using the <let> tag, which allows for reactive updates within the template.

Update state

Solid.js

Name.jsx

import { createSignal } from "solid-js";

export default function Name() {
  const [name, setName] = createSignal("John");
  setName("Jane");

  return <h1>Hello {name()}</h1>;
}

State updates in Solid.js are performed by calling the setter function returned by createSignal.

Marko

Name.marko

<let/name = "John"/>
<effect() { name = "Jane" }/>
<h1>Hello ${name}</h1>

In Marko, state updates can be managed using the <effect> tag, which allows for side effects and state updates within the template.

Computed state

Solid.js

DoubleCount.jsx

import { createSignal } from "solid-js";

export default function DoubleCount() {
  const [count] = createSignal(10);
  const doubleCount = () => count() * 2;

  return <div>{doubleCount()}</div>;
}

Computed properties in Solid.js are functions that derive values from other state, recalculating when dependencies change.

Marko

DoubleCount.marko

<let/count = 10/>
<const/doubleCount = count * 2/>
<div>${doubleCount}</div>

In Marko, computed properties are defined using the <const> tag, allowing for dynamic updates based on other data.

Templating

Templating in both frameworks allows for the creation of reusable and dynamic UI components.

Minimal template

Solid.js

HelloWorld.jsx

export default function HelloWorld() {
  return <h1>Hello World!</h1>;
}

Marko

HelloWorld.marko

<h1>Hello world</h1>

Styling

Styling in Solid.js and Marko can be managed using CSS, with support for scoped styles and CSS modules.

Solid.js

CssStyle.jsx

import "./style.css";

export default function CssStyle() {
  return (
    <>
      <h1 class="title">I am red</h1>
      <button style={{ "font-size": "10rem" }}>I am a button</button>
    </>
  );
}

style.css

.title {
  color: red;
}

Marko

CssStyle.marko

<h1.title>I am red</h1>
<button style={ fontSize: "10rem" }>I am a button</button>
<button class=scopedButton>I am a style-scoped button</button>

<style>
  .title {
    color: red;
  }
</style>
<style/{ scopedButton }>
  .scopedButton {
    font-size: 10rem;
  }
</style>

In Marko, styles can be scoped to specific elements using the <style> tag, allowing for modular and reusable styles.

Loop

Loops in both frameworks allow for the iteration over collections to dynamically generate UI elements.

Solid.js

Colors.jsx

import { For } from "solid-js";

export default function Colors() {
  const colors = ["red", "green", "blue"];

  return (
    <ul>
      <For each={colors}>{(color) => <li>{color}</li>}</For>
    </ul>
  );
}

Marko

Colors.marko

<ul>
  <for|color| of=["red", "green", "blue"]>
    <li>${color}</li>
  </for>
</ul>

Event click

Event handling in Solid.js and Marko is intuitive, allowing developers to respond to user interactions.

Solid.js

Counter.jsx

import { createSignal } from "solid-js";

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

  function incrementCount() {
    setCount(count() + 1);
  }

  return (
    <>
      <p>Counter: {count()}</p>
      <button onClick={incrementCount}>+1</button>
    </>
  );
}

Marko

Counter.marko

<let/count = 0/>
<p>Counter: ${count}</p>
<button onClick() { count++ }>+1</button>

Dom ref

DOM references in both frameworks allow for direct manipulation of DOM elements.

Solid.js

InputFocused.jsx

import { onMount } from "solid-js";

export default function InputFocused() {
  let inputElement;

  onMount(() => inputElement.focus());

  return <input ref={inputElement} type="text" />;
}

Marko

InputFocused.marko

<input/inputElement>
<effect() { inputElement().focus() }/>

Conditional

Conditional rendering in Solid.js and Marko allows for dynamic UI updates based on application state.

Solid.js

TrafficLight.jsx

import { createSignal, Switch, Match } from "solid-js";

const TRAFFIC_LIGHTS = ["red", "orange", "green"];

export default function TrafficLight() {
  const [lightIndex, setLightIndex] = createSignal(0);

  const light = () => TRAFFIC_LIGHTS[lightIndex()];

  function nextLight() {
    setLightIndex((lightIndex() + 1) % TRAFFIC_LIGHTS.length);
  }

  return (
    <>
      <button onClick={nextLight}>Next light</button>
      <p>Light is: {light()}</p>
      <p>
        You must
        <Switch>
          <Match when={light() === "red"}>
            <span>STOP</span>
          </Match>
          <Match when={light() === "orange"}>
            <span>SLOW DOWN</span>
          </Match>
          <Match when={light() === "green"}>
            <span>GO</span>
          </Match>
        </Switch>
      </p>
    </>
  );
}

Marko

TrafficLight.marko

static const TRAFFIC_LIGHTS = ["red", "orange", "green"];
<let/lightIndex = 0/>
<const/light = TRAFFIC_LIGHTS[lightIndex]/>

<button onClick() { lightIndex = (lightIndex + 1) % TRAFFIC_LIGHTS.length }>
  Next light
</button>
<p>Light is: ${light}</p>
<p>
  You must
  <if=light === "red">STOP</if>
  <else-if=light === "orange">SLOW DOWN</else-if>
  <else>GO</else>
</p>

Lifecycle

Lifecycle hooks in both frameworks provide a way to execute code at specific points in a component’s lifecycle.

On mount

Solid.js

PageTitle.jsx

import { createSignal, onMount } from "solid-js";

export default function PageTitle() {
  const [pageTitle, setPageTitle] = createSignal("");

  onMount(() => {
    setPageTitle(document.title);
  });

  return <p>Page title: {pageTitle()}</p>;
}

Marko

PageTitle.marko

<let/pageTitle = ""/>
<effect() { pageTitle = document.title }/>
<p>Page title: ${pageTitle}</p>

On unmount

Solid.js

Time.jsx

import { createSignal, onCleanup } from "solid-js";

export default function Time() {
  const [time, setTime] = createSignal(new Date().toLocaleTimeString());

  const timer = setInterval(() => {
    setTime(new Date().toLocaleTimeString());
  }, 1000);

  onCleanup(() => clearInterval(timer));

  return <p>Current time: {time()}</p>;
}

Marko

Time.marko

<let/time = new Date()/>
<lifecycle
  onMount() { this.timer = setInterval(_ => time = new Date(), 1000) }
  onDestroy() { clearInterval(this.timer) }
/>
<p>Current time: ${time.toLocaleTimeString()}</p>

Component composition

Component composition in Solid.js and Marko allows for the creation of complex UIs from smaller, reusable components.

Props

Solid.js

App.jsx

import UserProfile from "./UserProfile.jsx";

export default function App() {
  return (
    <UserProfile
      name="John"
      age={20}
      favouriteColors={["green", "blue", "red"]}
      isAvailable
    />
  );
}

Marko

App.marko

<UserProfile
  name="John"
  age=20
  favouriteColors=["green", "blue", "red"]
  isAvailable
/>

Emit to parent

Solid.js

App.jsx

import { createSignal } from "solid-js";
import AnswerButton from "./AnswerButton.jsx";

export default function App() {
  const [isHappy, setIsHappy] = createSignal(true);

  function onAnswerNo() {
    setIsHappy(false);
  }

  function onAnswerYes() {
    setIsHappy(true);
  }

  return (
    <>
      <p>Are you happy?</p>
      <AnswerButton onYes={onAnswerYes} onNo={onAnswerNo} />
      <p style={{ "font-size": "50px" }}>{isHappy() ? "😀" : "😥"}</p>
    </>
  );
}

Marko

App.marko

<let/isHappy = true/>
<p>Are you happy?</p>
<AnswerButton
  onYes() { isHappy = true }
  onNo() { isHappy = false }
/>
<p style={ fontSize: 50 }>${isHappy ? "😀" : "😥"}</p>

Slot

Solid.js

App.jsx

import FunnyButton from "./FunnyButton.jsx";

export default function App() {
  return <FunnyButton>Click me!</FunnyButton>;
}

Marko

App.marko

<FunnyButton>Click me!</FunnyButton>

Slot fallback

Solid.js

App.jsx

import FunnyButton from "./FunnyButton.jsx";

export default function App() {
  return (
    <>
      <FunnyButton />
      <FunnyButton>I got content!</FunnyButton>
    </>
  );
}

Marko

App.marko

<FunnyButton/>
<FunnyButton>I got content!</FunnyButton>

Context

Context management in Solid.js and Marko allows for the sharing of data and functionality across components.

Solid.js

App.jsx

import { createSignal } from "solid-js";

import { UserContext } from "./UserContext";
import UserProfile from "./UserProfile";

export default function App() {
  const [user, setUser] = createSignal({
    id: 1,
    username: "unicorn42",
    email: "unicorn42@example.com",
  });

  function updateUsername(newUsername) {
    setUser({ ...user(), username: newUsername });
  }

  return (
    <>
      <h1>Welcome back, {user().username}</h1>
      <UserContext.Provider value={[user, updateUsername]}>
        <UserProfile />
      </UserContext.Provider>
    </>
  );
}

Marko

App.marko

<let/user = {
  id: 1,
  username: "unicorn42",
  email: "unicorn42@example.com",
}/>
<const/updateUsername(newUsername) {
  user = { ...user, username: newUsername };
}/>

<h1>Welcome back, ${user.username}</h1>
<set={ ...user, updateUsername }>
  <UserProfile />
</set>

Form input

Form inputs in both frameworks support two-way data binding, making it easy to manage form state.

Input text

Solid.js

InputHello.jsx

import { createSignal } from "solid-js";

export default function InputHello() {
  const [text, setText] = createSignal("Hello world");

  function handleChange(event) {
    setText(event.target.value);
  }

  return (
    <>
      <p>{text()}</p>
      <input value={text()} onInput={handleChange} />
    </>
  );
}

Marko

InputHello.marko

<let/text = "Hello world"/>
<p>${text}</p>
<input value:=text/>

Checkbox

Solid.js

IsAvailable.jsx

import { createSignal } from "solid-js";

export default function IsAvailable() {
  const [isAvailable, setIsAvailable] = createSignal(false);

  function handleChange() {
    setIsAvailable((previousValue) => !previousValue);
  }

  return (
    <>
      <input
        id="is-available"
        type="checkbox"
        checked={isAvailable()}
        onChange={handleChange}
      />
      <label for="is-available">Is available</label>
    </>
  );
}

Marko

IsAvailable.marko

<input#is-available
  type="checkbox"
  checked:=input.isAvailable
/>
<label for="is-available">Is available</label>

Radio

Solid.js

PickPill.jsx

import { createSignal } from "solid-js";

export default function PickPill() {
  const [picked, setPicked] = createSignal("red");

  function handleChange(event) {
    setPicked(event.target.value);
  }

  return (
    <>
      <div>Picked: {picked()}</div>
      <input
        id="blue-pill"
        checked={picked() === "blue"}
        type="radio"
        value="blue"
        onChange={handleChange}
      />
      <label for="blue-pill">Blue pill</label>

      <input
        id="red-pill"
        checked={picked() === "red"}
        type="radio"
        value="red"
        onChange={handleChange}
      />
      <label for="red-pill">Red pill</label>
    </>
  );
}

Marko

PickPill.marko

<let/picked = "red"/>
<const/handleChange(event) {
  picked = event.target.value;
}/>

<div>Picked: ${picked}</div>
<input#blue-pill
  type="radio"
  checked=picked === "blue"
  value="blue"
  onChange=handleChange
/>
<label for="blue-pill">Blue pill</label>

<input#red-pill
  type="radio"
  checked=picked === "red"
  value="red"
  onChange=handleChange
/>
<label for="red-pill">Red pill</label>

Select

Solid.js

ColorSelect.jsx

import { createSignal, For } from "solid-js";

const colors = [
  { id: 1, text: "red" },
  { id: 2, text: "blue" },
  { id: 3, text: "green" },
  { id: 4, text: "gray", isDisabled: true },
];

export default function ColorSelect() {
  const [selectedColorId, setSelectedColorId] = createSignal(2);

  function handleChange(event) {
    setSelectedColorId(event.target.value);
  }

  return (
    <select value={selectedColorId()} onChange={handleChange}>
      <For each={colors}>
        {(color) => (
          <option value={color.id} disabled={color.isDisabled}>
            {color.text}
          </option>
        )}
      </For>
    </select>
  );
}

Marko

ColorSelect.marko

static const colors = [
  { id: 1, text: "red" },
  { id: 2, text: "blue" },
  { id: 3, text: "green" },
  { id: 4, text: "gray", isDisabled: true },
];
<let/selectedColorId = 2/>

<select onChange(event) { selectedColorId = event.target.value }>
  <for|{ id, isDisabled, text }| of=colors>
    <option value=id disabled=isDisabled selected=id === selectedColorId>
      ${text}
    </option>
  </for>
</select>

Webapp features

Webapp features in both frameworks include data fetching and rendering, with support for asynchronous operations.

Render app

Solid.js

index.html

<!DOCTYPE html>
<html>
  <body>
    <div id="app"></div>
    <script type="module" src="./main.jsx"></script>
  </body>
</html>

main.jsx

App.jsx

Marko

index.marko

<!DOCTYPE html>
<html>
  <App/>
</html>

App.marko

Fetch data

Solid.js

App.jsx

import { createResource, For, Switch, Match } from "solid-js";

async function fetchUsers() {
  return (await fetch("https://randomuser.me/api/?results=3")).json();
}

export default function App() {
  const [data] = createResource(fetchUsers);
  const users = () => data()?.results;

  return (
    <Switch>
      <Match when={data.loading}>
        <p>Fetching users...</p>
      </Match>
      <Match when={data.error}>
        <p>An error occurred while fetching users</p>
      </Match>
      <Match when={users()}>
        <ul>
          <For each={users()}>
            {(user) => (
              <li>
                <img src={user.picture.thumbnail} alt="user" />
                <p>
                  {user.name.first} {user.name.last}
                </p>
              </li>
            )}
          </For>
        </ul>
      </Match>
    </Switch>
  );
}

Marko

App.marko

<await(fetch("https://randomuser.me/api/?results=3").then(res => res.json()))>
  <@placeholder>
    <p>Fetching users...</p>
  </@placeholder>
  <@catch|error|>
    <p>An error occurred while fetching users</p>
  </@catch>
  <@then|{ results: users }|>
    <ul>
      <for|{ picture, name }| of=users>
        <li>
          <img src=picture.thumbnail alt="user">
          <p>${name.first} ${name.last}</p>
        </li>
      </for>
    </ul>
  </@then>
</await>






Decouvrez plus d’Offres de la plateform ItGalaxy.io :

Découvrez notre gamme complète de services et formations pour accélérer votre carrière.

1. Nous contactez

  • Description: Besoin de Formation et des Solutions cloud complètes pour vos applications
  • Links:

2. Infra as a Service

  • Description: Infrastructure cloud évolutive et sécurisée
  • Links:

3. Projets Développeurs


4. Développeurs


5. Formations Complètes


6. Marketplace

7. Blogs


This website is powered by ItGalaxy.io