Skip to Content

Solid

Solid TSX rules from eslint-plugin-solid.

Solid components compile to fine-grained reactivity, so patterns that look correct in React (destructuring props, calling useEffect-style hooks with array deps) silently break reactivity in Solid.

This family captures the common Solid-only pitfalls.

Source: eslint-plugin-solid (MIT).

Rule index

Each rule name links to the detailed section below.

Examples come from the checked lint corpus or package-level rule tests when project layout matters.

Rules

solid/components-return-once

Reject early and conditional return from a Solid component, Solid components must return exactly once at the top level.

Example:

import { Component } from "solid-js"; const App: Component<{ name: string }> = (props) => { // reports: solid/components-return-once (error) if (!props.name) return <span />; return <strong>{props.name}</strong>; };

solid/event-handlers

Require DOM event handler props to use canonical Solid casing (onClick, not onclick / onClIcK) so the compiler recognizes them as events.

Also flags on*-named props bound to non-function values, which look like handlers but are not.

Example:

import { createSignal } from "solid-js"; createSignal(0); // reports: solid/event-handlers (error) const tree = <button onclick="save">save</button>;

solid/imports

Route each Solid export to the correct entry point (solid-js, solid-js/web, or solid-js/store) and merge duplicate imports from the same entry.

Example:

// reports: solid/imports (error) import { createEffect, render } from "solid-js"; // reports: solid/imports (error) import { createStore } from "solid-js/web";

solid/jsx-no-duplicate-props

Reject duplicate JSX props on the same Solid element. Unlike React, Solid silently keeps the first value, so the duplicate is dead code and almost always a typo.

Example:

import { createSignal } from "solid-js"; createSignal(0); // reports: solid/jsx-no-duplicate-props (error) const tree = <div id="a" id="b" />;

solid/jsx-no-script-url

Reject javascript: URLs in Solid JSX attributes (href, src, …), they evaluate the suffix as code in the page context and are a long-standing XSS vector.

Example:

import { createSignal } from "solid-js"; createSignal(0); // reports: solid/jsx-no-script-url (error) const tree = <a href="javascript:alert(1)">click</a>;

solid/jsx-no-undef

Reject Solid JSX component names that are not declared or imported in scope.

Example:

import { createSignal } from "solid-js"; createSignal(0); // reports: solid/jsx-no-undef (error) const tree = <Missing />;

solid/jsx-uses-vars

Scope-marker compatibility rule (mirrors ESLint’s react/jsx-uses-vars).

The native engine emits no diagnostics for this id.

Example:

import { createSignal } from "solid-js"; createSignal(0); const Button = () => <button />; const tree = <Button />;

solid/no-array-handlers

Reject array values passed as Solid event handlers, Solid does not unwrap the array form React supports.

Example:

import { createSignal } from "solid-js"; const [enabled] = createSignal(false); // reports: solid/no-array-handlers (error) const tree = <button onClick={[enabled, () => enabled()]}>x</button>;

solid/no-destructure

Reject destructured Solid component props, destructuring breaks reactivity by reading the property eagerly.

Example:

import { Component } from "solid-js"; // reports: solid/no-destructure (error) const Hello: Component<{ name: string }> = ({ name }) => <span>{name}</span>;

solid/no-innerhtml

Reject innerHTML JSX attributes because they bypass sanitization and are a common XSS sink. A static string literal is still allowed by default; flip allowStatic off to ban that form too.

Example:

import { createSignal } from "solid-js"; const [html] = createSignal("<b>x</b>"); // reports: solid/no-innerhtml (error) const tree = <div innerHTML={html()} />;

solid/no-proxy-apis

Reject Solid APIs that rely on ES6 Proxy (including new Proxy, Proxy.revocable, imports from solid-js/store, and dynamic spread shapes through mergeProps).

For shipping to runtimes without Proxy support; off by default.

Example:

import { createSignal } from "solid-js"; createSignal(0); // reports: solid/no-proxy-apis (error) const handler = new Proxy({}, {});

solid/no-react-deps

Reject React-style dependency arrays in Solid tracked scopes (createEffect(() => ..., [deps])).

Example:

import { createEffect } from "solid-js"; // reports: solid/no-react-deps (error) createEffect(() => {}, []);

solid/no-react-specific-props

Reject React-specific JSX props such as className and htmlFor, Solid uses class and for.

Example:

import { createSignal } from "solid-js"; createSignal(0); // reports: solid/no-react-specific-props (error) const tree = <label className="primary" htmlFor="field" key="save" />;

solid/no-unknown-namespaces

Restrict namespaced JSX attributes (ns:name={...}) to the built-in Solid namespaces (on:, oncapture:, use:, prop:, attr:, bool:, style:, class:).

Extra names can be allowed through the allowedNamespaces option.

Example:

import { createSignal } from "solid-js"; createSignal(0); // reports: solid/no-unknown-namespaces (error) const tree = <div custom:active="true" />;

solid/prefer-classlist

Rewrite class={cn({ ... })} / clsx(...) / classnames(...) calls to the reactive classlist={{ ... }} prop.

Deprecated and off by default upstream.

Example:

import { createSignal } from "solid-js"; const clsx = (input: Record<string, unknown>) => Object.keys(input).join(" "); const [enabled] = createSignal(true); // reports: solid/prefer-classlist (error) const tree = <div class={clsx({ active: enabled() })} />;

solid/prefer-for

Replace inline array.map(item => <JSX />) with Solid’s <For> component so the iteration stays keyed and reactive instead of re-creating every child on each update.

Example:

import { createSignal } from "solid-js"; const [items] = createSignal([1, 2, 3]); // reports: solid/prefer-for (error) const tree = ( <section> {items().map((item) => ( <span>{item}</span> ))} </section> );

solid/prefer-show

Rewrite {cond && <JSX />} short-circuits in JSX to <Show when={cond}>...</Show>. Stylistic only, Solid’s compiler already handles the boolean form, so it is off by default.

Example:

import { createSignal } from "solid-js"; const [enabled] = createSignal(true); // reports: solid/prefer-show (error) const tree = <section>{enabled() && <strong>Ready</strong>}</section>;

solid/reactivity

Reject common Solid reactivity breakages, reading a signal outside a tracking scope, destructuring a Store, etc.

Example:

import { createEffect, createSignal } from "solid-js"; function App() { const [count] = createSignal(0); createEffect(async () => count()); // reports: solid/reactivity (error) return <span>{count}</span>; }

solid/self-closing-comp

Collapse JSX elements with no children to the self-closing form (<Foo></Foo> to <Foo />). Configurable per component vs HTML element, including a "void" mode that only enforces it for void tags.

Example:

import type { Component } from "solid-js"; const Icon: Component = () => <svg />; // reports: solid/self-closing-comp (error) const tree = <Icon></Icon>;

solid/style-prop

Require style={{...}} keys to be valid kebab-case CSS properties ("font-size", not React’s fontSize) and dimensioned values to be strings, Solid does not append implicit px.

Example:

import { createSignal } from "solid-js"; createSignal(0); // reports: solid/style-prop (error) const tree = <span style={{ fontSize: "12px" }} />;

solid/validate-jsx-nesting

Reject JSX nestings that the HTML parser would silently restructure at runtime, <p> cannot contain block-level children, <a> cannot contain another <a>, and <button> cannot contain other interactive elements.

Example:

const a = ( <p> {/* reports: solid/validate-jsx-nesting (error) */} <div>block in paragraph</div> </p> );
Last updated on