Skip to content

Commit 4caa3cb

Browse files
takujicamc314
authored andcommitted
allow the props name pattern only when the handler is "this.props.* or "props.*"
1 parent 182136c commit 4caa3cb

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

crates/oxc_linter/src/rules/react/jsx_handler_names.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ impl Rule for JsxHandlerNames {
282282
return;
283283
}
284284
if let Some((name, span, is_props_handler)) =
285-
get_event_handler_name_from_arrow_function(arrow_function, ctx)
285+
get_event_handler_name_from_arrow_function(arrow_function)
286286
{
287287
(Some(name), span, is_props_handler)
288288
} else {
@@ -297,7 +297,7 @@ impl Rule for JsxHandlerNames {
297297
}
298298
JSXExpression::StaticMemberExpression(member_expr) => {
299299
let (name, span, is_props_handler) =
300-
get_event_handler_name_from_static_member_expression(member_expr, ctx);
300+
get_event_handler_name_from_static_member_expression(member_expr);
301301
(Some(name), span, is_props_handler)
302302
}
303303
_ => {
@@ -316,13 +316,14 @@ impl Rule for JsxHandlerNames {
316316
}
317317
};
318318

319+
// "ref" prop is allowed to be assigned to a function with any name.
319320
if prop_key == "ref" {
320321
return;
321322
}
322323

323324
let prop_is_event_handler = self.match_event_handler_props_name(prop_key);
324325
let is_handler_name_correct = handler_name.as_ref().map_or(Some(false), |name| {
325-
// if the event handler is a property of "props", the handler name can also start with the prop prefix.
326+
// if the event handler is "this.props.*" or "props.*", the handler name can be the pattern of event handler props.
326327
if is_props_handler && self.match_event_handler_props_name(name).unwrap_or(false) {
327328
return Some(true);
328329
}
@@ -377,22 +378,23 @@ fn is_member_expression_callee(arrow_function: &ArrowFunctionExpression<'_>) ->
377378

378379
fn get_event_handler_name_from_static_member_expression(
379380
member_expr: &StaticMemberExpression,
380-
ctx: &LintContext,
381381
) -> (CompactStr, Span, bool) {
382382
let name = member_expr.property.name.as_str();
383383
let span = member_expr.property.span;
384384
match &member_expr.object {
385-
Expression::ThisExpression(_) => (name.into(), span, false),
386385
Expression::Identifier(ident) => {
387386
let obj_name = ident.name.as_str();
388-
(name.into(), span, obj_name == "props")
387+
(name.into(), span, obj_name == "props") // props.handleChange or obj.handleChange
389388
}
390389
Expression::StaticMemberExpression(expr) => {
391-
let (obj_name, _obj_span, is_props) =
392-
get_event_handler_name_from_static_member_expression(expr, ctx);
393-
(name.into(), span, !is_props && obj_name == "props")
390+
if let Expression::ThisExpression(_) = &expr.object {
391+
let obj_name = expr.property.name.as_str();
392+
(name.into(), span, obj_name == "props") // this.props.handleChange or this.obj.handleChange
393+
} else {
394+
(name.into(), span, false) // foo.props.handleChange, props.foo.handleChange, foo.bar.handleChange, etc.
395+
}
394396
}
395-
_ => (ctx.source_range(member_expr.span).into(), member_expr.span, false),
397+
_ => (name.into(), span, false), // this.handleChange
396398
}
397399
}
398400

@@ -453,7 +455,6 @@ fn test_normalize_handler_name() {
453455

454456
fn get_event_handler_name_from_arrow_function<'a>(
455457
arrow_function: &'a ArrowFunctionExpression<'a>,
456-
ctx: &LintContext<'a>,
457458
) -> Option<(CompactStr, Span, bool)> {
458459
if !arrow_function.expression {
459460
// Ignore arrow functions with block bodies like `() => { this.handleChange() }`.
@@ -471,7 +472,7 @@ fn get_event_handler_name_from_arrow_function<'a>(
471472
match &call_expr.callee {
472473
Expression::Identifier(ident) => Some((ident.name.as_str().into(), ident.span, false)),
473474
Expression::StaticMemberExpression(member_expr) => {
474-
Some(get_event_handler_name_from_static_member_expression(member_expr, ctx))
475+
Some(get_event_handler_name_from_static_member_expression(member_expr))
475476
}
476477
_ => None,
477478
}
@@ -622,6 +623,8 @@ fn test() {
622623
("<TestComponent onChange={this.handl3Change} />", None),
623624
("<TestComponent onChange={this.handle4change} />", None),
624625
("<TestComponent onChange={this.props.doSomethingOnChange} />", None),
626+
("<TestComponent onChange={this.props.obj.onChange} />", None),
627+
("<TestComponent onChange={props.obj.onChange} />", None),
625628
(
626629
"<TestComponent onChange={takeCareOfChange} />",
627630
Some(serde_json::json!([{ "checkLocalVariables": true }])),

crates/oxc_linter/src/snapshots/react_jsx_handler_names.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ source: crates/oxc_linter/src/tester.rs
5050
╰────
5151
help: Handler function for onChange prop key must be a camelCase name beginning with 'handle' only
5252

53+
⚠ eslint-plugin-react(jsx-handler-names): Invalid handler name: onChange
54+
╭─[jsx_handler_names.tsx:1:41]
55+
1 │ <TestComponent onChange={this.props.obj.onChange} />
56+
· ────────
57+
╰────
58+
help: Handler function for onChange prop key must be a camelCase name beginning with 'handle' only
59+
60+
⚠ eslint-plugin-react(jsx-handler-names): Invalid handler name: onChange
61+
╭─[jsx_handler_names.tsx:1:36]
62+
1 │ <TestComponent onChange={props.obj.onChange} />
63+
· ────────
64+
╰────
65+
help: Handler function for onChange prop key must be a camelCase name beginning with 'handle' only
66+
5367
⚠ eslint-plugin-react(jsx-handler-names): Invalid handler name: takeCareOfChange
5468
╭─[jsx_handler_names.tsx:1:26]
5569
1 │ <TestComponent onChange={takeCareOfChange} />

0 commit comments

Comments
 (0)