Skip to content

No Reset All State on Property Change

Suggestion
small-rules/no-reset-all-state-on-prop-change

Disallow resetting all state in an effect when a prop changes.

Rationale

Ported from eslint-plugin-react-you-might-not-need-an-effect/no-reset-all-state-on-property-change. The upstream rule points at the “Resetting all state when a prop changes” section of the React docs, so that’s where the intent comes from.

This flags an effect that resets every piece of state back to its initial value, keyed off a prop change. That’s a remount you’re implementing by hand, and it’s worse than a remount because you get an extra render with the stale state first.

React already has the primitive for this: pass the prop as key and the component remounts with fresh state, no effect required. It only works at the component boundary though, which is why the rule skips custom hooks, a hook can’t receive a key.

Diagnostic Messages

avoidResettingAllStateWhenAPropChanges
Avoid resetting all state when a prop changes. Instead, if "{{prop}}" is a key, pass it as "key" so React will reset the component's state.

Configuration

This rule accepts one options object after the severity.

environmentOptional

The React environment: 'roblox-ts' uses @rbxts/react, 'standard' uses react.

{
"jsPlugins": [
"@pobammer-ts/small-rules"
],
"rules": {
"small-rules/no-reset-all-state-on-prop-change": [
"error",
{
"environment": "roblox-ts"
}
]
}
}

Examples

Effect resets all state after a prop change
import React, { useEffect, useState } from "@rbxts/react";
declare function recordView(): void;
declare const utilities: {
readonly trackView: () => void;
};
export function ProfilePage({ userId }: { userId: string }): React.Element {
const [user, setUser] = useState<string | undefined>(undefined);
const [comment, setComment] = useState("type something");
recordView();
utilities.trackView();
useEffect(() => {
setUser(undefined);
setComment("type something");
}, [userId]);
return (
<frame>
<textlabel Text={user} />
<textlabel Text={comment} />
</frame>
);
}
Component reset with a key
import React, { useState } from "@rbxts/react";
export function ProfilePage(_properties: { key: string }): React.Element {
const [comment, setComment] = useState("type something");
return <textbox Text={comment} TextChanged={(textbox: { readonly Text: string }) => setComment(textbox.Text)} />;
}
export function Page({ userId }: { userId: string }): React.Element {
return <ProfilePage key={userId} />;
}