S
SolidJS15mo ago
aryzing

What's the most idiomatic way of forwarding an onClick event handler?

Given a Button component that wraps a <button>, what's the best way to forward the onClick handler? Seems handlers can be functions or tuples. When passing the prop directly to the button,
<button onClick={props.onClick}>...</button>
<button onClick={props.onClick}>...</button>
the linter complains that props.onClick is reactive, but handlers are not This is how I'm doing it currently,
export function Option(
props: ParentProps<{
onClick: JSX.HTMLElementTags["button"]["onClick"];
}>,
) {
const clickHandler: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent> = (
e,
) => {
if (!props.onClick) return;

if (typeof props.onClick === "function") return props.onClick(e);

props.onClick[0](props.onClick[1], e);
};
return (
<button
type="button"
onClick={clickHandler}
>
{props.children}
</button>
);
}
export function Option(
props: ParentProps<{
onClick: JSX.HTMLElementTags["button"]["onClick"];
}>,
) {
const clickHandler: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent> = (
e,
) => {
if (!props.onClick) return;

if (typeof props.onClick === "function") return props.onClick(e);

props.onClick[0](props.onClick[1], e);
};
return (
<button
type="button"
onClick={clickHandler}
>
{props.children}
</button>
);
}
10 Replies
Jules
Jules15mo ago
I use this method with no trouble, or linter errors, thus far, though I have no idea if it is the most idiomatic solution:
export const Button = (props: {
class?: string;
onClick?: (event: MouseEvent) => void;
children?: JSX.Element | string;
}) => {
// much of the functionality omited for brevity
return (
<button onClick={props.onClick} class={cn('btn', styles, props.class)}>{props.children}</button>
);
};
export const Button = (props: {
class?: string;
onClick?: (event: MouseEvent) => void;
children?: JSX.Element | string;
}) => {
// much of the functionality omited for brevity
return (
<button onClick={props.onClick} class={cn('btn', styles, props.class)}>{props.children}</button>
);
};
aryzing
aryzingOP15mo ago
Is the suggestion code above processed by Solid's ESLint plugin? An error is reported when reproducing the above code on a file processed by Solid's ESLint plugin,
import { VoidProps } from "solid-js";

export function Option(
props: VoidProps<{
text: string;
onClick?: (event: MouseEvent) => void;
}>,
) {
return (
<button type="button" onClick={props.onClick}>
{props.text}
</button>
);
}
import { VoidProps } from "solid-js";

export function Option(
props: VoidProps<{
text: string;
onClick?: (event: MouseEvent) => void;
}>,
) {
return (
<button type="button" onClick={props.onClick}>
{props.text}
</button>
);
}
the error,
The reactive variable 'props.onClick' should be wrapped in a function for reactivity. This includes event handler bindings on native elements, which are not reactive like other JSX props. eslint(solid/reactivity)
The reactive variable 'props.onClick' should be wrapped in a function for reactivity. This includes event handler bindings on native elements, which are not reactive like other JSX props. eslint(solid/reactivity)
Linter error info: https://github.com/solidjs-community/eslint-plugin-solid/blob/main/docs/reactivity.md
No description
bigmistqke
bigmistqke15mo ago
hu
bigmistqke
bigmistqke15mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke15mo ago
I initially thought it was a false positive bc the linter is quite aggressive but in this case the linter is correct, if you don't wrap the prop in a function it will not re-assign it if the prop ever updates. pretty unexpected behavior imo
REEEEE
REEEEE15mo ago
event handlers are not reactive afaik
bigmistqke
bigmistqke15mo ago
you know if this is mentioned anywhere in the old/new docs?
vaalha
vaalha15mo ago
GitHub
solid-primitives/packages/props at main · solidjs-community/solid-p...
A library of high-quality primitives that extend SolidJS reactivity. - solidjs-community/solid-primitives
Jules
Jules15mo ago
Yeah strangely it is - I don't know why I don't see the same error, am using plugin:solid/typescript
Want results from more Discord servers?
Add your server