@@ -753,22 +753,40 @@ const rule: TSESLint.RuleModule<MessageIds, []> = {
753
753
}
754
754
} ;
755
755
if ( node . type === "JSXExpressionContainer" ) {
756
- // Expect a function if the attribute is like onClick={} or on:click={}.
757
- // From the docs: Events are never rebound and the bindings are not
758
- // reactive, as it is expensive to attach and detach listeners. Since
759
- // event handlers are called like any other function each time an event
760
- // fires, there is no need for reactivity; simply shortcut your handler
761
- // if desired.
762
- // What this means here is we actually do consider an event handler a
763
- // tracked scope expecting a function, i.e. it's okay to use changing
764
- // props/signals in the body of the function, even though the changes
765
- // don't affect when the handler will run.
766
- const expect =
756
+ if (
767
757
node . parent ?. type === "JSXAttribute" &&
768
758
/ ^ o n [: A -Z ] / . test ( sourceCode . getText ( node . parent . name ) )
769
- ? "called-function"
770
- : "expression" ;
771
- pushTrackedScope ( node . expression , expect ) ;
759
+ ) {
760
+ // Expect a function if the attribute is like onClick={} or on:click={}.
761
+ // From the docs: Events are never rebound and the bindings are not
762
+ // reactive, as it is expensive to attach and detach listeners. Since
763
+ // event handlers are called like any other function each time an event
764
+ // fires, there is no need for reactivity; simply shortcut your handler
765
+ // if desired.
766
+ // What this means here is we actually do consider an event handler a
767
+ // tracked scope expecting a function, i.e. it's okay to use changing
768
+ // props/signals in the body of the function, even though the changes
769
+ // don't affect when the handler will run.
770
+ pushTrackedScope ( node . expression , "called-function" ) ;
771
+ } else if (
772
+ node . parent ?. type === "JSXAttribute" &&
773
+ node . parent . name . name === "value" &&
774
+ node . parent . parent ?. type === "JSXOpeningElement" &&
775
+ ( ( node . parent . parent . name . type === "JSXIdentifier" &&
776
+ node . parent . parent . name . name . endsWith ( "Provider" ) ) ||
777
+ ( node . parent . parent . name . type === "JSXMemberExpression" &&
778
+ node . parent . parent . name . property . name === "Provider" ) )
779
+ ) {
780
+ // From the docs: "The value passed to provider is passed to useContext as is. That means
781
+ // wrapping as a reactive expression will not work. You should pass in Signals and Stores
782
+ // directly instead of accessing them in the JSX."
783
+ // For `<SomeContext.Provider value={}>` or `<SomeProvider value={}>`, do nothing, the
784
+ // rule will warn later.
785
+ // TODO: add some kind of "anti- tracked scope" that still warns but enhances the error
786
+ // message if matched.
787
+ } else {
788
+ pushTrackedScope ( node . expression , "expression" ) ;
789
+ }
772
790
} else if ( node . type === "JSXSpreadAttribute" ) {
773
791
// allow <div {...props.nestedProps} />; {...props} is already ignored
774
792
pushTrackedScope ( node . argument , "expression" ) ;
0 commit comments