avoidInitializingStateAvoid initializing state in an effect. Instead, initialize "{{state}}"'s "useState()" with "{{arguments}}". For SSR hydration, prefer "useSyncExternalStore".small-rules/no-initialize-stateDisallow initializing state in an effect.
Ported from
eslint-plugin-react-you-might-not-need-an-effect/no-initialize-state.
The upstream rule points at TkDodo’s post on avoiding hydration mismatches with
useSyncExternalStore,
which is a web-React problem.
It’s a mount-only effect that synchronously sets state. You already have a place for initial values: the
useState() initializer. An effect that sets state means the first frame renders without the value. Then
the effect runs and it pops in a frame later. On the web that’s also a hydration mismatch, which is what the
upstream link is about. roblox-ts has no server render, so that half doesn’t apply here, but the
initial-value problem is the same.
The one real case is async init. You can’t await in an initializer, and the rule steps back when the state write happens inside an async callback. That’s the exception, not the rule.
avoidInitializingStateAvoid initializing state in an effect. Instead, initialize "{{state}}"'s "useState()" with "{{arguments}}". For SSR hydration, prefer "useSyncExternalStore".This rule accepts one options object after the severity.
import React, { useEffect, useState } from "@rbxts/react";
export function MyComponent(): React.Element { const [state, setState] = useState<string | undefined>();
useEffect(() => { setState("Hello"); }, []);
return <textlabel Text={state} />;}import React, { useEffect, useState } from "@rbxts/react";
declare const game: { readonly GetService: (service: string) => { readonly GetAsync: (url: string) => Promise<string> };};
export function MyComponent(): React.Element { const [state, setState] = useState<string | undefined>();
useEffect(() => { void (async (): Promise<void> => { const response = await game.GetService("HttpService").GetAsync("https://api.example.com/data"); setState(response); })(); }, []);
return <textlabel Text={state} />;}