no-useless-use-effect
Reports effect patterns that only move data around inside React instead of doing real side effects.
Rule details Suggestion
Section titled “Rule details ”SuggestionThis rule looks for useEffect, useLayoutEffect, and useInsertionEffect by default. It reports effects that are
better handled during render, in event handlers, or with a different hook.
The built-in reports are:
adjustState, state is adjusted from prop changesderivedState, state is only derived from props or other stateduplicateDeps, multiple effects use the same dependency listeffectChain, one effect depends on state written by another effect chainemptyEffect, the callback body is emptyeventFlag, an event is routed through a boolean flag in stateeventSpecificLogic, event logic runs later in an effect based on stateexternalStore, an external subscription syncs into state, useuseSyncExternalStoreinsteadinitializeState, state is initialized in an effect with a constant valuelogOnly, the effect only callsconsole.logmixedDerivedState, derived setter calls are mixed with other non-side-effect worknotifyParent, the effect only calls a parent callbackpassRefToParent, the effect passes a ref to a parent callbackresetState, state is reset from prop changes instead of using akey
Async effect callbacks are ignored.
Options
Section titled “Options”| Option | Default |
|---|---|
environment | "roblox-ts" |
hooks | ["useEffect", "useLayoutEffect", "useInsertionEffect"] |
propertyCallbackPrefixes | ["on"] |
refHooks | ["useRef"] |
stateHooks | ["useState", "useReducer"] |
reportAdjustState | true |
reportDerivedState | true |
reportDuplicateDeps | true |
reportEffectChain | true |
reportEmptyEffect | true |
reportEventFlag | true |
reportEventSpecificLogic | true |
reportExternalStore | true |
reportInitializeState | true |
reportLogOnly | true |
reportMixedDerivedState | true |
reportNotifyParent | true |
reportPassRefToParent | true |
reportResetState | true |
Configuration
Section titled “Configuration”import ceaseNonsense from "eslint-plugin-cease-nonsense";
export default [ { plugins: { "cease-nonsense": ceaseNonsense, }, rules: { "cease-nonsense/no-useless-use-effect": ["error", { environment: "roblox-ts", hooks: ["useEffect", "useLayoutEffect", "useInsertionEffect"], propertyCallbackPrefixes: ["on"], reportDerivedState: true, reportNotifyParent: true, reportEventFlag: true, }], }, },];Examples
Section titled “Examples” Incorrect
import { useEffect, useState } from "@rbxts/react";
function Profile(properties) { const [fullName, setFullName] = useState(""); useEffect(() => { setFullName(`${properties.first} ${properties.last}`); }, [properties.first, properties.last]);}
function Form(properties) { useEffect(() => { properties.onChange(properties.value); }, [properties.value, properties.onChange]);}
function SubmitButton() { const [submitted, setSubmitted] = useState(false); useEffect(() => { if (!submitted) return; submitForm(); setSubmitted(false); }, [submitted]);} Correct
function Profile(properties) { const fullName = `${properties.first} ${properties.last}`; return <textlabel Text={fullName} />;}
function Form(properties) { function handleSubmit() { properties.onChange(properties.value); } return <textbutton Event={{ Activated: handleSubmit }} />;}
function SubmitButton() { function handleSubmit() { submitForm(); } return <textbutton Event={{ Activated: handleSubmit }} />;}Related rules
Section titled “Related rules” require-named-effect-functions Requires named effect callbacks
use-exhaustive-dependencies Checks hook dependency lists
React Docs: You Might Not Need an Effect React guidance for effect-free patterns