Radix UI 无样式组件原语 has been discussed many times in the community, but as versions iterate, many conclusions need updating. This article revisits the topic based on the latest version.
Getting Started
The key lies in understanding the core logic:
const express = require('express')
const app = express()
app.use(express.json())
class AppError extends Error {
constructor(status, message) {
super(message); this.statusCode = status
}
}
const asyncHandler = (fn) => (req, res, next) =>
Promise.resolve(fn(req, res, next)).catch(next)
app.get('/api/users/:id', asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id)
if (!user) throw new AppError(404, '用户不存在')
res.json({ data: user })
}))
Performance optimization should be tailored to specific scenarios; not all cases require over-optimization.
Source Code Analysis
We can improve it in the following ways:
import { useReducer, useCallback } from 'react'
const initialState = { items: [], filter: '', sort: 'date' }
function reducer(state, action) {
switch (action.type) {
case 'SET_ITEMS': return { ...state, items: action.payload }
case 'SET_FILTER': return { ...state, filter: action.payload }
case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }
case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.payload) }
default: throw new Error(`Unknown: ${action.type}`)
}
}
This approach has been running stably in production for over six months and has been practically validated.
Real-World Applications
Let's start with the basic implementation:
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T
async function fetchUser(id: string) {
const res = await fetch(`/api/users/${id}`)
return res.json() as Promise<{ id: string; name: string; email: string }>
}
type User = UnwrapPromise<ReturnType<typeof fetchUser>>
// 类型安全的事件系统
interface EventMap {
login: { userId: string; timestamp: number }
logout: { userId: string }
}
class TypedEmitter<T extends Record<string, any>> {
private handlers = new Map<keyof T, Set<Function>>()
on<K extends keyof T>(event: K, handler: (payload: T[K]) => void) {
if (!this.handlers.has(event)) this.handlers.set(event, new Set())
this.handlers.get(event)!.add(handler)
}
emit<K extends keyof T>(event: K, payload: T[K]) {
this.handlers.get(event)?.forEach(h => h(payload))
}
}
This code demonstrates the basic usage. In real projects, you also need to consider error handling and edge cases.
Optimization Tips
Building on this foundation, we can further optimize:
const express = require('express')
const app = express()
app.use(express.json())
class AppError extends Error {
constructor(status, message) {
super(message); this.statusCode = status
}
}
const asyncHandler = (fn) => (req, res, next) =>
Promise.resolve(fn(req, res, next)).catch(next)
app.get('/api/users/:id', asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id)
if (!user) throw new AppError(404, '用户不存在')
res.json({ data: user })
}))
This pattern is very practical in large projects and can significantly reduce maintenance costs.
Summary
- Don't adopt new technology just for the sake of it
- Code examples are for reference only and need to be adjusted according to your business scenario
- Radix UI 无样式组件原语不是银弹,需要根据项目规模和技术栈选择
- Understanding underlying principles is more important than memorizing APIs