Skip to content

Commit b08fff8

Browse files
committed
After learning that event listeners are reactive on components, adjusted rule to warn only on native elements.
1 parent 1db5114 commit b08fff8

File tree

3 files changed

+14
-3
lines changed

3 files changed

+14
-3
lines changed

docs/reactivity.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ function Component() {
438438
return <div on:click={() => console.log(signal())} />;
439439
}
440440

441+
const Parent = (props) => {
442+
return <Child onClick={props.onClick} />;
443+
};
444+
441445
const Component = (props) => {
442446
const [signal] = createSignal();
443447
return (

src/rules/reactivity.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ const rule: TSESLint.RuleModule<MessageIds, []> = {
238238
untrackedReactive:
239239
"The reactive variable '{{name}}' should be used within JSX, a tracked scope (like createEffect), or inside an event handler function.",
240240
expectedFunctionGotExpression:
241-
"The reactive variable '{{name}}' should be wrapped in a function for reactivity. This includes event handler bindings, which are not reactive like other JSX props.",
241+
"The reactive variable '{{name}}' should be wrapped in a function for reactivity. This includes event handler bindings on native elements, which are not reactive like other JSX props.",
242242
badSignal:
243243
"The reactive variable '{{name}}' should be called as a function when used in {{where}}.",
244244
badUnnamedDerivedSignal:
@@ -755,7 +755,10 @@ const rule: TSESLint.RuleModule<MessageIds, []> = {
755755
if (node.type === "JSXExpressionContainer") {
756756
if (
757757
node.parent?.type === "JSXAttribute" &&
758-
/^on[:A-Z]/.test(sourceCode.getText(node.parent.name))
758+
/^on[:A-Z]/.test(sourceCode.getText(node.parent.name)) &&
759+
node.parent.parent?.type === "JSXOpeningElement" &&
760+
node.parent.parent.name.type === "JSXIdentifier" &&
761+
isDOMElementName(node.parent.parent.name.name)
759762
) {
760763
// Expect a function if the attribute is like onClick={} or on:click={}. From the docs:
761764
// Events are never rebound and the bindings are not reactive, as it is expensive to

test/rules/reactivity.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ export const cases = run("reactivity", rule, {
165165
const [signal, setSignal] = createSignal(1);
166166
return <div on:click={() => console.log(signal())} />;
167167
}`,
168+
// event listeners are reactive on components
169+
`const Parent = props => {
170+
return <Child onClick={props.onClick} />;
171+
}`,
168172
// Pass reactive variables as-is into provider value prop
169173
`const Component = props => {
170174
const [signal] = createSignal();
@@ -544,7 +548,7 @@ export const cases = run("reactivity", rule, {
544548
},
545549
],
546550
},
547-
// event listeners not rebound
551+
// event listeners are not rebound on native elements
548552
{
549553
code: `
550554
const Component = props => {

0 commit comments

Comments
 (0)