
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Solid.js is a declarative JavaScript library for building user interfaces. It focuses on fine-grained reactivity, which allows for highly efficient updates and minimal re-renders. Solid.js is designed to be fast and simple, providing a reactive programming model that is easy to understand and use.
Reactive State Management
Solid.js uses fine-grained reactivity for state management. The `createSignal` function creates a reactive state that updates the UI efficiently when the state changes.
import { createSignal } from 'solid-js';
function Counter() {
const [count, setCount] = createSignal(0);
return (
<div>
<button onClick={() => setCount(count() + 1)}>Increment</button>
<p>Count: {count()}</p>
</div>
);
}
JSX Support
Solid.js supports JSX, allowing you to write HTML-like syntax within JavaScript. This makes it easy to create and manage UI components.
import { render } from 'solid-js/web';
function App() {
return (
<div>
<h1>Hello, Solid.js!</h1>
</div>
);
}
render(() => <App />, document.getElementById('root'));
Component Composition
Solid.js allows for easy component composition. You can create reusable components and pass data to them via props.
function Greeting(props) {
return <h1>Hello, {props.name}!</h1>;
}
function App() {
return (
<div>
<Greeting name="Solid.js" />
</div>
);
}
Direct DOM Manipulation
Solid.js provides direct DOM manipulation capabilities. The `onCleanup` function allows you to perform cleanup tasks, such as clearing intervals, when a component is unmounted.
import { onCleanup } from 'solid-js';
function Timer() {
let timerId;
const [time, setTime] = createSignal(0);
const startTimer = () => {
timerId = setInterval(() => setTime(time() + 1), 1000);
};
onCleanup(() => clearInterval(timerId));
return (
<div>
<p>Time: {time()}</p>
<button onClick={startTimer}>Start Timer</button>
</div>
);
}
React is a popular JavaScript library for building user interfaces. It uses a virtual DOM and a component-based architecture. Compared to Solid.js, React has a larger ecosystem and community but may have more overhead due to its virtual DOM.
Vue.js is a progressive JavaScript framework for building user interfaces. It features a reactive data binding system and a component-based architecture. Vue.js is similar to Solid.js in its reactivity model but offers more built-in features and a larger ecosystem.
Svelte is a compiler that converts declarative components into efficient imperative code that directly manipulates the DOM. Unlike Solid.js, Svelte does not use a virtual DOM and compiles components at build time, resulting in highly optimized and fast applications.
Solid is yet another declarative Javascript library for creating user interfaces. It does not use a Virtual DOM. Instead it opts to compile it's templates down to real DOM nodes and wrap updates in fine grained computations. This way when your state updates only the code that depends on it runs.
const HelloMessage = ({name}) => (
<div>
Hello {name}
</div>
);
createRoot(() =>
document
.getElementById("hello-example")
.appendChild(<HelloMessage name="Taylor" />)
);
To use Solid with JSX (recommended) run:
> npm install solid-js babel-plugin-jsx-dom-expressions
You can also run Solid from the browser directly with your flavor of renderer found in the Solid Standalone package.
For example get started with Tagged Template Literal version in the browser by simply including a script tag on the page.
<script src="https://unpkg.com/solid-standalone/html.min.js"></script>
It all starts with State. State objects are immutable so to update you call their companion setter function. Through the use of proxies they give the control of an immutable interface and the performance of a mutable one. Note only Plain Objects and Arrays are deeply wrapped.
import { createState, onCleanup } from 'solid-js'
const CountingComponent = () => {
const [state, setState] = createState({counter: 0});
const interval = setInterval(() =>
setState({counter: state.counter + 1})
, 1000);
onCleanup(() => clearInterval(interval));
return <div>{(state.counter)}</div>;
}
You can also deep set:
const [state, setState] = createState({
user: {
firstName: 'John'
lastName: 'Smith'
}
});
setState('user', {firstName: 'Jake', middleName: 'Reese'});
You can also use functions:
const [state, setState] = createState({counter: 0});
setState('counter', c => c + 1);
This takes the form similar to ImmutableJS setIn for leaving all mutation control at the top level state object. Keep in mind that setState when setting an object attempts to merge instead of replace.
But where the magic happens is with computations(effects and memos) which automatically track dependencies.
createEffect(() =>
setState({
displayName: `${state.user.firstName} ${state.user.lastName}`
})
);
console.log(state.displayName); // Jake Smith
Whenever any dependency changes the State value will immediately update. JSX expressions can also be wrapped in effects so for something as trivial as a display name you could just inline the expression in the template and have it update automatically.
Solid State also exposes a reconcile method used with setState that does deep diffing to allow for automatic efficient interopt with immutable store technologies like Redux, Apollo, or RxJS.
const unsubscribe = store.subscribe(({ todos }) => (
setState(reconcile('todos', todos)));
);
onCleanup(() => unsubscribe());
Solid's rendering is done by the DOM Expressions library. This library provides a generic optimized runtime for fine grained libraries like Solid with the opportunity to use a number of different Rendering APIs. The best option is to use JSX pre-compilation with Babel Plugin JSX DOM Expressions to give the smallest code size, cleanest syntax, and most performant code. The compiler converts JSX to native DOM element instructions and wraps expressions to be wrapped in our computations when indicated by in inner parens {( )}
.
Prettier and some compile to JS libraries like CoffeeScript will strip Parenthesis causing issues with Solid's JSX. So unfortunately they are incompatible at this time.
To get setup add this babel plugin config to your .babelrc, webpack, or rollup config:
"plugins": ["jsx-dom-expressions"]
And include at the top of your files:
import { r } from 'solid-js/dom'
Alternatively in non-compiled environments you can use Tagged Template Literals Lit DOM Expressions or even HyperScript with Hyper DOM Expressions.
For convenience Solid exports interfaces to runtimes for these as:
import { h } from 'solid-js/h';
import { html } from 'solid-js/html'
Remember you still need to install the library separately for these to work.
Templates in Solid are just Pascal(Capital) cased functions. Their first argument is an props object and return real DOM nodes. Other than that nothing is special about them.
const Parent = () => (
<section>
<Label greeting='Hello'>
<div>John</div>
</Label>
</section>
);
const Label = ({greeting, children}) => (
<>
<div>{greeting}</div>
{children}
</>
);
Since the all nodes from JSX are actual DOM nodes the only responsibility of top level Templates/Components is appending to the DOM. Since change management is independent of code modularization, Solid Templates are sufficient as is to act as Components, or Solid fits easily into other Component structures like Web Components.
import { createState, createRoot } from 'solid-js'
class Component extends HTMLElement {
constructor () {
const [state, setState] = createState({});
const [props, __setProps] = createState({});
Object.assign(this, {state, setState, props, __setProps});
}
connectedCallback() {
!this.shadowRoot && this.attachShadow({mode: 'open'});
createRoot(dispose => {
this.dispose = dispose;
this.shadowRoot.appendChild(this.render());
}
}
diconnectedCallback() { this.dispose && this.dispose(); }
attributeChangedCallback(attr, oldVal, newVal) {
this.__setProps({[attr]: newVal});
}
}
class MyComponent extends Component {
constuctor () {
super();
this.setState({greeting: 'World'});
}
render() {
return <div>Hello {(state.greeting)}</div>
}
}
This project started as trying to find a small performant library to work with Web Components, that had easy interopt with existing standards. It is very inspired by fine grain change detection libraries like Knockout.js and RxJS. The idea here is to ease users into the world of Observable programming by keeping it transparent and starting simple. Classically the Virtual DOM as seen in React for all it's advances has some signifigant trade offs:
<div />
is not longer just a divSo the driving questions here are:
Admittedly it takes a strong reason to not go with the general consensus of best, and most supported libraries and frameworks. And React's Hooks API addresses the majority of what I once considered it's most untenable faults. But I believe there is a better way out there than how we do it today.
I cover this in more detail in my Bring Your Own Framework Blog Series(links below).
This project is still a work in progress. While Solid's change management is reaching stability (this repo), I am still refining the rendering APIs from the DOM Expressions.
FAQs
A declarative JavaScript library for building user interfaces.
The npm package solid-js receives a total of 197,047 weekly downloads. As such, solid-js popularity was classified as popular.
We found that solid-js demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer 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
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.