如何封装react组件
封装React组件的核心方法
将UI和逻辑分离,通过props传递数据和回调函数 使用TypeScript或PropTypes定义清晰的接口类型 保持组件单一职责原则,避免过度复杂化
基本封装模式
创建独立的组件文件(.jsx/.tsx) 定义可复用的样式和布局结构 暴露必要的props接口供外部调用 内部状态管理使用useState/useReducer
// Button组件示例
const Button = ({
variant = 'primary',
size = 'medium',
onClick,
children
}) => {
const baseStyle = 'rounded font-medium transition-colors';
const sizeStyles = {
small: 'py-1 px-3 text-sm',
medium: 'py-2 px-4 text-base',
large: 'py-3 px-6 text-lg'
};
return (
<button
className={`${baseStyle} ${sizeStyles[size]}`}
onClick={onClick}
data-variant={variant}
>
{children}
</button>
);
};
高阶组件(HOC)封装
通过函数包装现有组件增强功能 共享通用逻辑和上下文 保持组件树清晰可调试
function withLoading(Component) {
return function EnhancedComponent({ isLoading, ...props }) {
return isLoading ? (
<div className="loading-spinner" />
) : (
<Component {...props} />
);
};
}
自定义Hook封装
将复杂逻辑抽离为可复用Hook 组合多个原生Hook实现业务需求 保持组件视图层简洁
// 使用自定义Hook管理表单状态
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
const handleChange = (e) => {
const { name, value } = e.target;
setValues(prev => ({ ...prev, [name]: value }));
};
return { values, handleChange };
}
// 组件中使用
function LoginForm() {
const { values, handleChange } = useForm({
email: '',
password: ''
});
return (
<form>
<input
name="email"
value={values.email}
onChange={handleChange}
/>
</form>
);
}
上下文封装模式
通过Context API共享全局状态 创建Provider组件管理数据流 配合自定义Hook简化消费逻辑
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prev => prev === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// 封装消费Hook
function useTheme() {
return useContext(ThemeContext);
}
复合组件模式
通过多个关联组件组合实现复杂UI 使用React.Children和cloneElement管理子组件 保持组件API的一致性和灵活性

function Tabs({ children }) {
const [activeTab, setActiveTab] = useState(0);
return (
<div className="tabs-container">
<div className="tabs-header">
{Children.map(children, (child, index) => (
cloneElement(child, {
isActive: index === activeTab,
onClick: () => setActiveTab(index)
})
))}
</div>
</div>
);
}
function Tab({ isActive, onClick, children }) {
return (
<button
className={`tab ${isActive ? 'active' : ''}`}
onClick={onClick}
>
{children}
</button>
);
}






