Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/ffsshhttiikk/opencode-agents-skills --skill react명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
SOC 직업 분류 기준
| name | react |
| description | React development best practices and patterns |
| license | MIT |
| compatibility | opencode |
| metadata | {"audience":"developers","category":"frameworks"} |
When creating React components, hooks, or applications.
import React, { useState, useCallback, useMemo } from 'react';
interface UserCardProps {
user: User;
onEdit?: (user: User) => void;
onDelete?: (userId: string) => void;
isSelected?: boolean;
}
export const UserCard: React.FC<UserCardProps> = ({
user,
onEdit,
onDelete,
isSelected = false,
}) => {
const [isExpanded, setIsExpanded] = useState(false);
const handleEdit = useCallback(() => {
onEdit?.(user);
}, [user, onEdit]);
const handleDelete = useCallback(() => {
onDelete?.(user.id);
}, [user.id, onDelete]);
return (
<div className={`user-card ${isSelected ? 'selected' : ''}`}>
<div className="user-header" onClick={() => setIsExpanded(!isExpanded)}>
<img src={user.avatarUrl} alt={user.name} />
<div>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
<button onClick={handleEdit}>Edit</button>
<button onClick={handleDelete} disabled={user.isProtected}>
Delete
</button>
</div>
{isExpanded && (
<div className="user-details">
<p>Role: {user.role}</p>
<p>Created: {new Date(user.createdAt).toLocaleDateString()}</p>
)}
);
};
// Compound components
interface TabsProps {
defaultTab: string;
children: React.ReactNode;
}
export function Tabs({ defaultTab, children }: TabsProps) {
const [activeTab, setActiveTab] = useState(defaultTab);
const context = useMemo(() => ({ activeTab, setActiveTab }), [activeTab]);
return <TabsContext.Provider value={context}>{children}</TabsContext.Provider>;
}
Tabs.Tab = function Tab({ id, children }: { id: string; children: React.ReactNode }) {
const { activeTab, setActiveTab } = useContext(TabsContext);
return (
<button onClick={() => setActiveTab(id)} className={activeTab === id ? 'active' : ''}>
{children}
</button>
);
};
Tabs.Panel = function Panel({ id, children }: { id: string; children: React.ReactNode }) {
const { activeTab } = useContext(TabsContext);
return activeTab === id ? <div>{children}</div> : null;
};
import { useState, useEffect, useCallback } from 'react';
export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
export function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch {
return initialValue;
}
});
const setValue = useCallback((value: T | ((val: T) => T)) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
(valueToStore);
..(key, .(valueToStore));
} (error) {
.(, error);
}
}, [key, storedValue]);
[storedValue, setValue] ;
}
// Use React.memo for component memoization
export const ExpensiveList = React.memo<ExpensiveListProps>(({ items, onSelect }) => {
return (
<ul>
{items.map(item => (
<ListItem key={item.id} item={item} onSelect={onSelect} />
))}
</ul>
);
}, (prevProps, nextProps) => {
// Custom comparison
return prevProps.items.length === nextProps.items.length;
});
// Use useMemo for expensive calculations
const sortedItems = useMemo(() => {
return [...items].sort((a, b) => b.score - a.score);
}, [items]);
// Use useCallback for stable function references
const handleSelect = useCallback((id: string) => {
onSelect(id);
}, [onSelect]);
// Lazy loading
const HeavyComponent = .( ());
() {
(
);
}