Skills Plugins MCP Prompt Model 博客 我的中心

frontend-patterns

Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices.

DeepseekModel Curated skill Quality Excellent · 90 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-zh-tw-skills-frontend-patterns-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name frontend-patterns description Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices. 前端開發模式 用於 React、Next.js 和高效能使用者介面的現代前端模式。 元件模式 組合優於繼承 // PASS: 良好:元件組合 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 > } // 使用方式 < Card > < CardHeader > 標題 </ CardHeader > < CardBody > 內容 </ 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 > ) } // 使用方式 < Tabs defaultTab= "overview" > < TabList > < Tab id = "overview" > 概覽 </ Tab > < Tab id = "details" > 詳情 </ Tab > </ TabList > </ Tabs > Render Props 模式 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)} </> } // 使用方式 < 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] } // 使用方式 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 ) // 將最新的 fetcher/options 保存在 ref 中,讓 refetch 即使在呼叫端 // 傳入行內函式與物件字面值時也能保持參照穩定。 // 若沒有這麼做,每次渲染都會建立新的 refetch,下方的 effect 會在 // 每次狀態更新後重新執行,造成無限取得迴圈。 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 } } // 使用方式 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) } ) Debounce 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 } // 使用方式 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 用於昂貴計算 // 排序前先複製 - Array.prototype.sort 會就地修改陣列 const sortedMarkets = useMemo ( () => { return [...markets]. sort ( ( a, b ) => b. volume - a. volume ) }, [markets]) // PASS: useCallback 用於傳遞給子元件的函式 const handleSearch = useCallback ( ( query : string ) => { setSearchQuery (query) }, []) // PASS: React.memo 用於純元件 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: 延遲載入重型元件 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 , // 預估行高 overscan : 5 // 額外渲染的項目數 }) 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 = '名稱為必填' } else if (formData. name . length > 200 ) { newErrors. name = '名稱必須少於 200 個字元' } if (!formData. description . trim ()) { newErrors. description = '描述為必填' } if (!formData. endDate ) { newErrors. endDate = '結束日期為必填' } setErrors (newErrors) return Object . keys (newErrors). length === 0 } const handleSubmit = async ( e : React . FormEvent ) => { e. preventDefault () if (! validate ()) return try { await createMarket (formData) // 成功處理 } catch (error) { // 錯誤處理 } } return ( < form onSubmit = {handleSubmit} > < input value = {formData.name} onChange = {e => setFormData(prev => ({ ...prev, name: e.target.value }))} placeholder="市場名稱" />
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。