开发编程
#react
frontend-patterns
React、Next.js、状态管理、性能优化和UI最佳实践的前端开发模式。
DeepseekModel
官方收录技能
质量 优秀 · 90
v1.0.0
获取
https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-zh-cn-skills-frontend-patterns-skill-md&format=skill
下载 .skill
标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name frontend-patterns description React、Next.js、状态管理、性能优化和UI最佳实践的前端开发模式。 origin ECC 前端开发模式 适用于 React、Next.js 和高性能用户界面的现代前端模式。 何时激活 构建 React 组件(组合、属性、渲染) 管理状态(useState、useReducer、Zustand、Context) 实现数据获取(SWR、React Query、服务器组件) 优化性能(记忆化、虚拟化、代码分割) 处理表单(验证、受控输入、Zod 模式) 处理客户端路由和导航 构建可访问、响应式的 UI 模式 组件模式 组合优于继承 // PASS: GOOD: Component composition interface CardProps { children : React . ReactNode variant ?: 'default' | 'outlined' } export function Card ( { children, variant = 'default' }: CardProps ) { return < div className = { ` card card- ${ variant }`}> {children} </ div > } export function CardHeader ( { children }: { children: React.ReactNode } ) { return < div className = "card-header" > {children} </ div > } export function CardBody ( { children }: { children: React.ReactNode } ) { return < div className = "card-body" > {children} </ div > } // Usage < Card > < CardHeader > Title </ CardHeader > < CardBody > Content </ CardBody > </ Card > 复合组件 interface TabsContextValue { activeTab : string setActiveTab : ( tab : string ) => void } const TabsContext = createContext< TabsContextValue | undefined >( undefined ) export function Tabs ( { children, defaultTab }: { children: React.ReactNode defaultTab: string } ) { const [activeTab, setActiveTab] = useState (defaultTab) return ( < TabsContext.Provider value = {{ activeTab , setActiveTab }}> {children} </ TabsContext.Provider > ) } export function TabList ( { children }: { children: React.ReactNode } ) { return < div className = "tab-list" > {children} </ div > } export function Tab ( { id, children }: { id: string , children: React.ReactNode } ) { const context = useContext ( TabsContext ) if (!context) throw new Error ( 'Tab must be used within Tabs' ) return ( < button className = {context.activeTab === id ? ' active ' : ''} onClick = {() => context.setActiveTab(id)} > {children} </ button > ) } // Usage < Tabs defaultTab= "overview" > < TabList > < Tab id = "overview" > Overview </ Tab > < Tab id = "details" > Details </ Tab > </ TabList > </ Tabs > 渲染属性模式 interface DataLoaderProps <T> { url : string children : ( data : T | null , loading : boolean , error : Error | null ) => React . ReactNode } export function DataLoader <T>({ url, children }: DataLoaderProps <T>) { const [data, setData] = useState<T | null >( null ) const [loading, setLoading] = useState ( true ) const [error, setError] = useState< Error | null >( null ) useEffect ( () => { fetch (url) . then ( res => res. json ()) . then (setData) . catch (setError) . finally ( () => setLoading ( false )) }, [url]) return <> {children(data, loading, error)} </> } // Usage < DataLoader < Market []> url= "/api/markets" > { ( markets, loading, error ) => { if (loading) return < Spinner /> if (error) return < Error error = {error} /> return < MarketList markets = {markets!} /> }} </ DataLoader > 自定义 Hooks 模式 状态管理 Hook export function useToggle ( initialValue = false ): [ boolean , () => void ] { const [value, setValue] = useState (initialValue) const toggle = useCallback ( () => { setValue ( v => !v) }, []) return [value, toggle] } // Usage const [isOpen, toggleOpen] = useToggle () 异步数据获取 Hook interface UseQueryOptions <T> { onSuccess ?: ( data : T ) => void onError ?: ( error : Error ) => void enabled ?: boolean } export function useQuery<T>( key : string , fetcher : () => Promise <T>, options ?: UseQueryOptions <T> ) { const [data, setData] = useState<T | null >( null ) const [error, setError] = useState< Error | null >( null ) const [loading, setLoading] = useState ( false ) // Keep the latest fetcher/options in refs so refetch stays referentially // stable even when callers pass inline functions and object literals. // Without this, every render creates a new refetch, and the effect below // re-runs after each state update - an infinite fetch loop. const fetcherRef = useRef (fetcher) const optionsRef = useRef (options) useEffect ( () => { fetcherRef. current = fetcher optionsRef. current = options }) const refetch = useCallback ( async () => { setLoading ( true ) setError ( null ) try { const result = await fetcherRef. current () setData (result) optionsRef. current ?. onSuccess ?.(result) } catch (err) { const error = err as Error setError (error) optionsRef. current ?. onError ?.(error) } finally { setLoading ( false ) } }, []) const enabled = options?. enabled !== false useEffect ( () => { if (enabled) { refetch () } }, [key, enabled, refetch]) return { data, error, loading, refetch } } // Usage const { data : markets, loading, error, refetch } = useQuery ( 'markets' , () => fetch ( '/api/markets' ). then ( r => r. json ()), { onSuccess : data => console . log ( 'Fetched' , data. length , 'markets' ), onError : err => console . error ( 'Failed:' , err) } ) 防抖 Hook export function useDebounce<T>( value : T, delay : number ): T { const [debouncedValue, setDebouncedValue] = useState<T>(value) useEffect ( () => { const handler = setTimeout ( () => { setDebouncedValue (value) }, delay) return () => clearTimeout (handler) }, [value, delay]) return debouncedValue } // Usage const [searchQuery, setSearchQuery] = useState ( '' ) const debouncedQuery = useDebounce (searchQuery, 500 ) useEffect ( () => { if (debouncedQuery) { performSearch (debouncedQuery) } }, [debouncedQuery]) 状态管理模式 Context + Reducer 模式 interface State { markets : Market [] selectedMarket : Market | null loading : boolean } type Action = | { type : 'SET_MARKETS' ; payload : Market [] } | { type : 'SELECT_MARKET' ; payload : Market } | { type : 'SET_LOADING' ; payload : boolean } function reducer ( state : State , action : Action ): State { switch (action. type ) { case 'SET_MARKETS' : return { ...state, markets : action. payload } case 'SELECT_MARKET' : return { ...state, selectedMarket : action. payload } case 'SET_LOADING' : return { ...state, loading : action. payload } default : return state } } const MarketContext = createContext<{ state : State dispatch : Dispatch < Action > } | undefined >( undefined ) export function MarketProvider ( { children }: { children: React.ReactNode } ) { const [state, dispatch] = useReducer (reducer, { markets : [], selectedMarket : null , loading : false }) return ( < MarketContext.Provider value = {{ state , dispatch }}> {children} </ MarketContext.Provider > ) } export function useMarkets ( ) { const context = useContext ( MarketContext ) if (!context) throw new Error ( 'useMarkets must be used within MarketProvider' ) return context } 性能优化 记忆化 // PASS: useMemo for expensive computations // Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo ( () => { return [...markets]. sort ( ( a, b ) => b. volume - a. volume ) }, [markets]) // PASS: useCallback for functions passed to children const handleSearch = useCallback ( ( query : string ) => { setSearchQuery (query) }, []) // PASS: React.memo for pure components export const MarketCard = React . memo < MarketCardProps >( ( { market } ) => { return ( < div className = "market-card" > < h3 > {market.name} </ h3 > < p > {market.description} </ p > </ div > ) }) 代码分割与懒加载 import { lazy, Suspense } from 'react' // PASS: Lazy load heavy components const HeavyChart = lazy ( () => import ( './HeavyChart' )) const ThreeJsBackground = lazy ( () => import ( './ThreeJsBackground' )) export function Dashboard ( ) { return ( < div > < Suspense fallback = { < ChartSkeleton /> }> < HeavyChart data = {data} /> </ Suspense > < Suspense fallback = {null} > < ThreeJsBackground /> </ Suspense > </ div > ) } 长列表虚拟化 import { useVirtualizer } from '@tanstack/react-virtual' export function VirtualMarketList ( { markets }: { markets: Market[] } ) { const parentRef = useRef< HTMLDivElement >( null ) const virtualizer = useVirtualizer ({ count : markets. length , getScrollElement : () => parentRef. current , estimateSize : () => 100 , // Estimated row height overscan : 5 // Extra items to render }) return ( < div ref = {parentRef} style = {{ height: ' 600px ', overflow: ' auto ' }}> < div style = {{ height: `${ virtualizer.getTotalSize ()} px `, position: ' relative ' }} > {virtualizer.getVirtualItems().map(virtualRow => ( < div key = {virtualRow.index} style = {{ position: ' absolute ', top: 0 , left: 0 , width: ' 100 %', height: `${ virtualRow.size } px `, transform: ` translateY (${ virtualRow.start } px )` }} > < MarketCard market = {markets[virtualRow.index]} /> </ div > ))} </ div > </ div > ) } 表单处理模式 带验证的受控表单 interface FormData { name : string description : string endDate : string } interface FormErrors { name ?: string description ?: string endDate ?: string } export function CreateMarketForm ( ) { const [formData, setFormData] = useState< FormData >({ name : '' , description : '' , endDate : '' }) const [errors, setErrors] = useState< FormErrors >({}) const validate = (): boolean => { const newErrors : FormErrors = {} if (!formData. name . trim ()) { newErrors. name = 'Name is required' } else if (formData. name . length > 200 ) { newErrors. name = 'Name must be under 200 characters' } if (!formData. description . trim ()) { newErrors. description = 'Description is required' } if (!formData. endDate ) { newErrors. endDate = 'End date is required' } setErrors (newErrors) return Object . keys (newErrors). length === 0 } const handleSubmit = async ( e : React . FormEvent ) => { e. preventDefault () if (! validate ()) return try { await createMarket (formData) // Success handling } catch (error) { // Error handling } } return ( <form onSubmit={handleSubmit}> <input value={formData.name}
Agent 识别该技能的关键词,点击任意一个即可复制。
该技能未提供触发词。
下载的 .skill 包内含以下字段。
| 字段 | 说明 |
|---|---|
| format | 格式标识(skill/v1) |
| skill_id | 技能唯一 ID |
| name | 技能名称 |
| version | 版本号 |
| description | 技能描述 |
| category | 所属分类(数组) |
| trigger_words | 触发词列表 |
| tags | 标签列表 |
| source | 来源标识 |
| source_url | 来源链接(本页地址) |
| exported_at | 导出时间(每次下载生成) |
| system_prompt | 系统提示词正文 |
| model_config | 模型参数:provider / model / temperature / max_tokens / top_p |
| examples | 示例 |
| install_guide | 各平台导入说明(Coze / Dify / Claude / 自定义框架) |