skills/react-hooks-state/SKILL.md
React Hooks 與狀態管理模式。用於自訂 Hooks 設計、useReducer 複雜狀態、Context 架構、Server State 整合、表單狀態處理。
npx skillsauth add vincent119/ai-rules-kit react-hooks-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.
封裝可重用邏輯,回傳值與操作函式:
import { useState, useEffect, useCallback } from 'react';
interface UseAsyncResult<T> {
data: T | null;
error: Error | null;
loading: boolean;
execute: () => Promise<void>;
}
export function useAsync<T>(asyncFn: () => Promise<T>): UseAsyncResult<T> {
const [data, setData] = useState<T | null>(null);
const [error, setError] = useState<Error | null>(null);
const [loading, setLoading] = useState(false);
const execute = useCallback(async () => {
setLoading(true);
setError(null);
try {
const result = await asyncFn();
setData(result);
} catch (err) {
setError(err instanceof Error ? err : new Error(String(err)));
} finally {
setLoading(false);
}
}, [asyncFn]);
return { data, error, loading, execute };
}
多個相關狀態變更用 reducer 集中管理:
import { useReducer } from 'react';
interface FormState {
values: Record<string, string>;
errors: Record<string, string>;
isSubmitting: boolean;
}
type FormAction =
| { type: 'SET_FIELD'; field: string; value: string }
| { type: 'SET_ERROR'; field: string; error: string }
| { type: 'CLEAR_ERRORS' }
| { type: 'SUBMIT_START' }
| { type: 'SUBMIT_END' };
function formReducer(state: FormState, action: FormAction): FormState {
switch (action.type) {
case 'SET_FIELD':
return {
...state,
values: { ...state.values, [action.field]: action.value },
errors: { ...state.errors, [action.field]: '' },
};
case 'SET_ERROR':
return {
...state,
errors: { ...state.errors, [action.field]: action.error },
};
case 'CLEAR_ERRORS':
return { ...state, errors: {} };
case 'SUBMIT_START':
return { ...state, isSubmitting: true };
case 'SUBMIT_END':
return { ...state, isSubmitting: false };
}
}
export function useForm(initialValues: Record<string, string>) {
const [state, dispatch] = useReducer(formReducer, {
values: initialValues,
errors: {},
isSubmitting: false,
});
const setField = (field: string, value: string) =>
dispatch({ type: 'SET_FIELD', field, value });
const setError = (field: string, error: string) =>
dispatch({ type: 'SET_ERROR', field, error });
return { ...state, setField, setError, dispatch };
}
避免 prop drilling,提供型別安全的 Context:
import { createContext, useContext, useReducer, type ReactNode } from 'react';
// 1. 定義型別
interface AuthState {
user: User | null;
token: string | null;
}
type AuthAction =
| { type: 'LOGIN'; user: User; token: string }
| { type: 'LOGOUT' };
interface AuthContextValue {
state: AuthState;
login: (user: User, token: string) => void;
logout: () => void;
}
// 2. 建立 Context(不給預設值,用 null 搭配 guard)
const AuthContext = createContext<AuthContextValue | null>(null);
// 3. 自訂 hook(含 null check)
export function useAuth(): AuthContextValue {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}
// 4. Provider
function authReducer(state: AuthState, action: AuthAction): AuthState {
switch (action.type) {
case 'LOGIN':
return { user: action.user, token: action.token };
case 'LOGOUT':
return { user: null, token: null };
}
}
export function AuthProvider({ children }: { children: ReactNode }) {
const [state, dispatch] = useReducer(authReducer, { user: null, token: null });
const login = (user: User, token: string) =>
dispatch({ type: 'LOGIN', user, token });
const logout = () => dispatch({ type: 'LOGOUT' });
return (
<AuthContext.Provider value={{ state, login, logout }}>
{children}
</AuthContext.Provider>
);
}
import { useEffect, useRef } from 'react';
// 資料載入:搭配 cleanup 避免 race condition
export function useUser(userId: string) {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
let cancelled = false;
async function fetchUser() {
const res = await fetch(`/api/users/${userId}`);
const data = await res.json();
if (!cancelled) setUser(data);
}
fetchUser();
return () => { cancelled = true; };
}, [userId]);
return user;
}
// 事件監聽:使用 ref 避免重新綁定
export function useEventListener(
event: string,
handler: (e: Event) => void,
element: HTMLElement | Window = window,
) {
const handlerRef = useRef(handler);
handlerRef.current = handler;
useEffect(() => {
const listener = (e: Event) => handlerRef.current(e);
element.addEventListener(event, listener);
return () => element.removeEventListener(event, listener);
}, [event, element]);
}
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
// 查詢
export function useUsers() {
return useQuery({
queryKey: ['users'],
queryFn: () => fetch('/api/users').then((res) => res.json()),
staleTime: 5 * 60 * 1000,
});
}
// 變更 + 自動更新快取
export function useCreateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (newUser: CreateUserInput) =>
fetch('/api/users', {
method: 'POST',
body: JSON.stringify(newUser),
headers: { 'Content-Type': 'application/json' },
}).then((res) => res.json()),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] });
},
});
}
{ data, loading, error, action } 結構tools
基於 SLA/SLO 量化評估事故影響的計算模型與業務影響矩陣。適用於「SLA 影響」、「SLO 違反」、「影響評估」、「營收損失估算」、「Error Budget」、「可用性計算」、「事故成本評估」等量化事故業務影響的任務。強化 impact-assessor 的評估能力。注意:事故原因分析與改善規劃不在此技能範圍內。
research
根因分析(RCA)方法論詳細指南。提供 5 Whys、Fishbone 圖、Fault Tree Analysis、變更分析等結構化 RCA 技術,以及認知偏誤防範清單。適用於「根因分析」、「RCA」、「5 Whys」、「魚骨圖」、「Fault Tree」、「原因分析方法論」、「變更分析」等事故原因分析任務。強化 root-cause-investigator 的分析能力。注意:時間軸重建與改善規劃不在此技能範圍內。
testing
事故事後分析(Postmortem)完整流程。協調 7 個執行階段:資訊收集 → 時間軸重建 → 根因分析 → 影響評估 → 改善規劃 → 報告審查 → 整合報告,最終產出完整的 Postmortem 報告。適用於「寫事故報告」、「post-incident 分析」、「RCA 報告」、「事故時間軸整理」、「建立改善措施」等請求。注意:即時 Incident Response(on-call)、監控系統設定、告警配置不在此技能範圍內。
content-media
投影片版面模式庫。提供 20 種投影片類型的最佳版面配置、格線系統、色彩與字型設計 Token。適用於「投影片版面」、「Slide Layout」、「設計系統」、「格線」、「字型」、「色彩規範」等投影片視覺設計任務。強化 visual-designer 的設計能力。注意:PPT/Keynote 檔案直接輸出不在此技能範圍內。