Should I disable `solid/reactivity` linter warning in this case?

I frequently run into this warning with event handlers. Here's an example:
type PropsType = {
something: string;
}

const SomeComponent = (props: PropsType) => {
// eslint-plugin-solid complains with the following
// warning:
//
// This function should be passed to a tracked scope
// (like createEffect) or an event handler because it
// contains reactivity, or else changes will be
// ignored solid/reactivity
const handleInput = (value: string) => {
print(props.something, value);
}

return (
<input onClick={(event) => handleInput(event.currentTarget.value)} />
);
}
type PropsType = {
something: string;
}

const SomeComponent = (props: PropsType) => {
// eslint-plugin-solid complains with the following
// warning:
//
// This function should be passed to a tracked scope
// (like createEffect) or an event handler because it
// contains reactivity, or else changes will be
// ignored solid/reactivity
const handleInput = (value: string) => {
print(props.something, value);
}

return (
<input onClick={(event) => handleInput(event.currentTarget.value)} />
);
}

Is there a problem with this code? If so, what's wrong with it? Otherwise, should I disable this warning in situations like this one?
12 Replies
peerreynders
peerreynders2mo ago
Try
import type { JSX } from 'solid-js';

type PropsType = {
something: string;
};

const SomeComponent = (props: PropsType) => {
const handleInput: JSX.InputEventHandler<HTMLInputElement, InputEvent> = (
e
) => {
print(props.something, e.currentTarget.value);
};
return <input onClick={handleInput} />;
};
import type { JSX } from 'solid-js';

type PropsType = {
something: string;
};

const SomeComponent = (props: PropsType) => {
const handleInput: JSX.InputEventHandler<HTMLInputElement, InputEvent> = (
e
) => {
print(props.something, e.currentTarget.value);
};
return <input onClick={handleInput} />;
};
The parameter types let the linting rule know that it's not a regular function but an event handler destined to be used in Solid's JSX.
João Bezerra
João Bezerra2mo ago
What if I need to pass something else to the handler other than the event?
peerreynders
peerreynders2mo ago
You create the event handler where the "something else" will be included in the eventhandler's closure. That's exactly what happens with props.something.
João Bezerra
João Bezerra2mo ago
Right, but then I wouldn't be able to use InputEventHandler.
peerreynders
peerreynders2mo ago
Look at the example. handleInput uses props.something and it's still an InputEventHandler.
João Bezerra
João Bezerra2mo ago
Let me give a concrete example.
import { For } from "solid-js"

type PropsType = {
something: string;
}

const SomeComponent = (props: PropsType) => {
const [items, setItems] = createSignal(["One", "Two", "Three"]);

const handleInput = (item: string, value: string) => {
print(props.something, item, value);
}

return (
<div>
<For each={items()}>
{(item) => (
<input onClick={(event) => handleInput(item, event.currentTarget.value)} />
)}
</For>
</div>
);
}
import { For } from "solid-js"

type PropsType = {
something: string;
}

const SomeComponent = (props: PropsType) => {
const [items, setItems] = createSignal(["One", "Two", "Three"]);

const handleInput = (item: string, value: string) => {
print(props.something, item, value);
}

return (
<div>
<For each={items()}>
{(item) => (
<input onClick={(event) => handleInput(item, event.currentTarget.value)} />
)}
</For>
</div>
);
}
Could I define handleInput outside the jsx and still be able to access item without running into the linter warning?
peerreynders
peerreynders2mo ago
I would try this:
type PropsType = {
something: string;
};

function makeHandler(item: string, props: PropsType) {
const handler: JSX.InputEventHandler<HTMLInputElement, InputEvent> = (
event
) => {
print(props.something, item, event.currentTarget.value);
};
return handler;
}

const SomeComponent = (props: PropsType) => {
const [items, setItems] = createSignal(['One', 'Two', 'Three']);

return (
<div>
<For each={items()}>
{(item) => <input onClick={makeHandler(item, props)} />}
</For>
</div>
);
};
type PropsType = {
something: string;
};

function makeHandler(item: string, props: PropsType) {
const handler: JSX.InputEventHandler<HTMLInputElement, InputEvent> = (
event
) => {
print(props.something, item, event.currentTarget.value);
};
return handler;
}

const SomeComponent = (props: PropsType) => {
const [items, setItems] = createSignal(['One', 'Two', 'Three']);

return (
<div>
<For each={items()}>
{(item) => <input onClick={makeHandler(item, props)} />}
</For>
</div>
);
};
Or perhaps more simply:
import { For } from 'solid-js';

type PropsType = {
something: string;
};

function doIt(item: string, something: string, value: string) {
print(something, item, value);
}

const SomeComponent = (props: PropsType) => {
const [items, setItems] = createSignal(['One', 'Two', 'Three']);

return (
<div>
<For each={items()}>
{(item) => (
<input
onClick={(e) => doIt(item, props.something, e.currentTarget.value)}
/>
)}
</For>
</div>
);
};
import { For } from 'solid-js';

type PropsType = {
something: string;
};

function doIt(item: string, something: string, value: string) {
print(something, item, value);
}

const SomeComponent = (props: PropsType) => {
const [items, setItems] = createSignal(['One', 'Two', 'Three']);

return (
<div>
<For each={items()}>
{(item) => (
<input
onClick={(e) => doIt(item, props.something, e.currentTarget.value)}
/>
)}
</For>
</div>
);
};
João Bezerra
João Bezerra2mo ago
Oh, I hadn't thought of putting the event handler outside of the component function. Is this a common idiom?
peerreynders
peerreynders2mo ago
I wouldn't say so, it's just something I naturally arrived at because I'm not fond of anonymous inline functions, During the first beta: https://github.com/peerreynders/solid-start-todomvc-kcd-v2/blob/d3ba9953c83f3777b66fda375bc588e139ca8452/src/routes/%5B...todos%5D.tsx#L848-L913 Though for all I know it now triggers linter warnings 🤷
GitHub
solid-start-todomvc-kcd-v2/src/routes/[...todos].tsx at d3ba9953c83...
TodoMVC inspired by kentcdodds/remix-todomvc implemented with SolidStart - peerreynders/solid-start-todomvc-kcd-v2
João Bezerra
João Bezerra2mo ago
I see. Would you say then that, of the people that use eslint-plugin-solid, most just disable the warning?
peerreynders
peerreynders2mo ago
Not that I'm aware of
João Bezerra
João Bezerra2mo ago
Okay, thanks for your help!