react — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited react (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<!-- target: ~2600 tokens (real tiktoken count) | 17 rules with severity classification -->
Purpose: Prevents the React-specific mistakes LLMs make repeatedly — wrong state placement, stale closures, unnecessary re-renders, and broken async patterns. Concrete rules with code examples.
Where these rules don't strictly apply: test fixtures, Storybook stories, design-system primitives in isolation, and small in-tutorial demo components may legitimately differ. The rules below apply to production application code.
// Avoid: form state lifted to page-level parent
function Page() {
const [email, setEmail] = useState('');
return <Form email={email} setEmail={setEmail} />;
}
// Prefer: state lives in the component that uses it
function Form() {
const [email, setEmail] = useState('');
return <input value={email} onChange={e => setEmail(e.target.value)} />;
}<UserAvatar>, <OrderSummary> rather than one <ProfilePage> that does everything. Exception: pages that are mostly markup with little logic may exceed 100 lines.userId through four components to reach a button is a design smell. // Avoid: drilling through intermediaries
<Layout userId={userId}><Sidebar userId={userId}><Nav userId={userId} /></Sidebar></Layout>
// Prefer: context or render-prop composition
<UserContext.Provider value={userId}><Layout /></UserContext.Provider> // Wrong
function Parent() {
const Child = () => <div>hello</div>; // new reference every render
return <Child />;
}
// Correct: define outside
const Child = () => <div>hello</div>;
function Parent() { return <Child />; } // Wrong
const [items, setItems] = useState([]);
items.push(newItem); // mutation — React does not re-render
setItems(items);
// Correct
setItems(prev => [...prev, newItem]); // Avoid
const [fullName, setFullName] = useState('');
useEffect(() => { setFullName(`${first} ${last}`); }, [first, last]);
// Prefer
const fullName = `${first} ${last}`; // Wrong: ref for displayed value
const count = useRef(0);
count.current++; // UI never updates
// Wrong: state for a timer ID
const [timerId, setTimerId] = useState(null); // triggers re-render on set
// Correct
const timerId = useRef(null);exhaustive-deps must be enabled and respected. // Wrong: stale closure over userId
useEffect(() => { fetchUser(userId); }, []); // runs once, userId never updates
// Correct
useEffect(() => { fetchUser(userId); }, [userId]); useEffect(() => {
const controller = new AbortController();
fetch(`/api/user/${id}`, { signal: controller.signal })
.then(r => r.json())
.then(setUser)
.catch(err => { if (err.name !== 'AbortError') setError(err); });
return () => controller.abort();
}, [id]); // Wrong
if (isLoggedIn) { const user = useUser(); }
// Correct
const user = useUser(); // hook always called; handle null inside // Avoid: re-sorts on every render including unrelated state changes
const sorted = items.sort((a, b) => a.name.localeCompare(b.name));
// Prefer
const sorted = useMemo(
() => [...items].sort((a, b) => a.name.localeCompare(b.name)),
[items]
); // Wrong: new object reference every render
<Chart options={{ color: 'red', width: 400 }} />
// Correct: stable reference
const chartOptions = useMemo(() => ({ color: 'red', width: 400 }), []);
<Chart options={chartOptions} /> const Dashboard = React.lazy(() => import('./Dashboard'));
function App() {
return (
<Suspense fallback={<Spinner />}>
<Dashboard />
</Suspense>
);
} // Wrong
{items.map((item, i) => <Row key={i} item={item} />)}
// Correct: stable, unique identity
{items.map(item => <Row key={item.id} item={item} />)} // Avoid
expect(wrapper.find('.submit-btn').exists()).toBe(true);
// Prefer
expect(screen.getByRole('button', { name: /submit/i })).toBeInTheDocument();null silently on error are invisible bugs in production. it('shows error message when fetch fails', async () => {
server.use(rest.get('/api/user', (req, res, ctx) => res(ctx.status(500))));
render(<UserProfile id="1" />);
expect(await screen.findByText(/something went wrong/i)).toBeInTheDocument();
});fetch or using MSW keeps tests closer to real behavior than mocking useUser directly.min-width media queries for larger viewports.These rules target the exact failure modes that appear in LLM-generated React code: state lifted too high, effects without cleanup, index keys, inline object props, and derived state stored redundantly. Each rule is actionable in a single code review comment and includes a before/after example that makes the correct pattern unambiguous. The MUST/SHOULD/AVOID classification means hook-correctness rules are strict and stylistic rules respect context.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.