avoidEventHandlerAvoid using state and effects as an event handler. Instead, call the code that uses "{{name}}" directly when the event occurs.small-rules/no-event-handlerDisallow using state and an effect as an event handler.
Ported from
eslint-plugin-react-you-might-not-need-an-effect/no-event-handler.
The upstream rule points at the “Sharing logic between event
handlers”
section of the React docs, so that’s where the intent comes from.
This flags effects whose body is an if-guard around logic that reads state or props. That’s an event handler wearing an effect costume: the condition is the event, the body is the handler. The difference matters because an effect runs after render and only when its dependencies change, so the logic fires late and on a render schedule instead of when the user actually does the thing.
In Roblox the event is a TextChanged, Activated, or similar callback. Put the logic there, or in the
parent if it reads props. The rule only catches the if-guard shape though, so it won’t find every disguised
handler, it’s a heuristic.
avoidEventHandlerAvoid using state and effects as an event handler. Instead, call the code that uses "{{name}}" directly when the event occurs.avoidPropHandlerAvoid using props and effects as an event handler. Instead, move the code that uses "{{name}}" to the parent component.This rule accepts one options object after the severity.
import React, { useEffect, useState } from "@rbxts/react";
declare const os: { readonly clock: () => number;};
declare function submitData(data: { readonly name: string }): void;
export function Form(): React.Element { const [name, setName] = useState(""); const [dataToSubmit, setDataToSubmit] = useState<{ readonly name: string } | undefined>();
useEffect(() => { if (dataToSubmit !== undefined && os.clock() % 2 === 0) { submitData(dataToSubmit); } }, [dataToSubmit]);
return ( <frame> <textbox Text={name} TextChanged={(textbox: { readonly Text: string }) => setName(textbox.Text)} /> <textbutton Text="Submit" Activated={() => setDataToSubmit({ name })} /> </frame> );}import React, { useState } from "@rbxts/react";
declare function submitData(data: { readonly name: string }): void;
export function Form(): React.Element { const [name, setName] = useState(""); // oxlint-disable-next-line no-unused-vars, sonar/no-unused-vars, small-rules/no-dead-store -- The setter stays unused; the handler submits the state directly. const [dataToSubmit, setDataToSubmit] = useState<{ readonly name: string } | undefined>();
function handleSubmit(): void { if (dataToSubmit !== undefined) { submitData(dataToSubmit); } }
return ( <frame> <textbox Text={name} TextChanged={(textbox: { readonly Text: string }) => setName(textbox.Text)} /> <textbutton Text="Submit" Activated={handleSubmit} /> </frame> );}