skills/react-use-state/SKILL.md
Guides proper usage of React useState hook. Use this skill when adding state to components, deciding between useState vs alternatives, or troubleshooting state update issues.
npx skillsauth add Chris-Maskey/opencode-config react-use-stateInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
useState is a React Hook that adds a state variable to your component, triggering re-renders when the state changes.
const [state, setState] = useState(initialState);
| Use Case | Example |
|----------|---------|
| Form inputs | const [name, setName] = useState('') |
| UI state | const [isOpen, setIsOpen] = useState(false) |
| Simple counters | const [count, setCount] = useState(0) |
| Local component data | const [items, setItems] = useState([]) |
When you need mutable values that don't trigger re-renders:
// Interval IDs, DOM references, previous values
const intervalRef = useRef(null);
const inputRef = useRef(null);
When state logic is complex:
// Multiple related values, complex transitions
const [state, dispatch] = useReducer(reducer, initialState);
Use useReducer when:
If a value can be computed from props or other state, don't store it:
// BAD: Redundant state
const [fullName, setFullName] = useState('');
useEffect(() => {
setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);
// GOOD: Compute during render
const fullName = `${firstName} ${lastName}`;
// If expensive, use useMemo
const sortedItems = useMemo(() =>
items.sort((a, b) => a.name.localeCompare(b.name)),
[items]
);
For state shared across multiple components:
// BAD: Mutation
obj.x = 10;
setObj(obj); // React ignores this!
// GOOD: Create new object
setObj({ ...obj, x: 10 });
// BAD: Array mutation
arr.push(item);
setArr(arr); // React ignores this!
// GOOD: Create new array
setArr([...arr, item]);
function handleClick() {
setCount(count + 1);
console.log(count); // Still old value!
// If you need the new value:
const nextCount = count + 1;
setCount(nextCount);
console.log(nextCount); // New value
}
// BAD: Only increments by 1
function handleClick() {
setCount(count + 1); // 0 + 1 = 1
setCount(count + 1); // 0 + 1 = 1 (same stale value!)
setCount(count + 1); // 0 + 1 = 1
}
// GOOD: Increments by 3
function handleClick() {
setCount(c => c + 1); // 0 -> 1
setCount(c => c + 1); // 1 -> 2
setCount(c => c + 1); // 2 -> 3
}
// BAD: createTodos() runs every render
const [todos, setTodos] = useState(createTodos());
// GOOD: createTodos runs only once
const [todos, setTodos] = useState(createTodos);
// Or with arrow function for arguments
const [todos, setTodos] = useState(() => createTodos(userId));
// BAD: Conditional hook
if (condition) {
const [state, setState] = useState(0); // Error!
}
// GOOD: Always call, conditionally use
const [state, setState] = useState(0);
if (condition) {
// use state here
}
// Parent controls reset via key
<Form key={version} />
// When version changes, Form remounts with fresh state
// BAD: Function gets called
const [fn, setFn] = useState(someFunction);
// GOOD: Wrap in arrow function
const [fn, setFn] = useState(() => someFunction);
setFn(() => newFunction);
// Object: spread and override
setForm({ ...form, email: newEmail });
// Nested object
setUser({
...user,
address: { ...user.address, city: newCity }
});
// Array: filter, map, spread
setItems(items.filter(i => i.id !== id)); // Remove
setItems([...items, newItem]); // Add
setItems(items.map(i => i.id === id ? {...i, done: true} : i)); // Update
setState unconditionally during render| Hook | Use When |
|------|----------|
| useState | Simple state, primitives, basic objects |
| useReducer | Complex state logic, multiple sub-values |
| useRef | Mutable values without re-renders |
| useMemo | Expensive computed values |
| useContext | State shared across component tree |
tools
Anti-patterns and mistakes to avoid as a product manager. Use when evaluating leadership behaviors, improving team dynamics, reflecting on management practices, or onboarding new product managers.
development
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
testing
Design effective CTAs using visual attention and gaze psychology principles. Use when designing landing pages, button hierarchies, conversion elements, or optimizing user attention flow through interfaces.
tools
Run agent-browser + Chrome inside Vercel Sandbox microVMs for browser automation from any Vercel-deployed app. Use when the user needs browser automation in a Vercel app (Next.js, SvelteKit, Nuxt, Remix, Astro, etc.), wants to run headless Chrome without binary size limits, needs persistent browser sessions across commands, or wants ephemeral isolated browser environments. Triggers include "Vercel Sandbox browser", "microVM Chrome", "agent-browser in sandbox", "browser automation on Vercel", or any task requiring Chrome in a Vercel Sandbox.