React 18 如何封装可复用组件以支持父组件包裹子组件调用
实现可包裹的复合React组件
基础实现:满足包裹式调用+静态子组件
你需要把原来的MyCustomComponent从普通对象改成React组件,同时将Header、Content挂载为该组件的静态属性,这样既可以用包裹形式使用父组件,又能通过父组件访问子组件,同时父组件还能接收children和其他自定义props。
代码实现:
import React from 'react'; // 定义子组件,可根据业务需求扩展props const Header: React.FC = () => { return <header>自定义Header</header>; }; const Content: React.FC = () => { return <main>自定义Content</main>; }; // 父包裹组件,接收children及任意额外props const MyCustomComponent: React.FC<{ children: React.ReactNode; // 可添加其他明确的props类型,或者用[ key: string ]: any接收任意props className?: string; }> = ({ children, className }) => { // 这里可以添加父组件的逻辑:比如统一布局、样式、全局事件监听等 return ( <div className={`my-custom-container ${className || ''}`}> {children} </div> ); }; // 将子组件挂载为父组件的静态属性 MyCustomComponent.Header = Header; MyCustomComponent.Content = Content; export default MyCustomComponent;
调用方式:
import MyCustomComponent from './MyCustomComponent'; const App = () => { return ( <MyCustomComponent className="app-container"> <MyCustomComponent.Header /> <MyCustomComponent.Content /> {/* 支持添加任意自定义子元素 */} <div className="extra-content">额外的子内容</div> </MyCustomComponent> ); };
进阶实现:强制子组件必须在父组件内使用+共享状态
如果需要确保子组件只能在父组件包裹下使用,同时让父子组件共享状态,可以通过React Context实现:
import React, { createContext, useContext, useState, ReactNode } from 'react'; // 创建Context,默认值设为null const MyCustomContext = createContext<{ sharedState: string; updateSharedState: (val: string) => void; } | null>(null); // 自定义Hook,用于消费Context,若不在父组件内则抛出错误 const useMyCustomContext = () => { const context = useContext(MyCustomContext); if (!context) { throw new Error('MyCustomComponent的子组件必须在MyCustomComponent内部使用'); } return context; }; // 子组件通过Hook获取父组件的共享状态 const Header: React.FC = () => { const { sharedState } = useMyCustomContext(); return <header>Header - 当前状态:{sharedState}</header>; }; const Content: React.FC = () => { const { sharedState, updateSharedState } = useMyCustomContext(); return ( <main> <p>Content - 当前状态:{sharedState}</p> <button onClick={() => updateSharedState('状态已更新')}>更新状态</button> </main> ); }; // 父组件管理状态并提供Context const MyCustomComponent: React.FC<{ children: ReactNode }> = ({ children }) => { const [sharedState, setSharedState] = useState('初始状态'); return ( <MyCustomContext.Provider value={{ sharedState, updateSharedState: setSharedState }}> <div className="my-custom-container"> {children} </div> </MyCustomContext.Provider> ); }; // 挂载子组件到父组件 MyCustomComponent.Header = Header; MyCustomComponent.Content = Content; export default MyCustomComponent;
这种实现下,如果直接在MyCustomComponent外部调用MyCustomComponent.Header或Content,会立即抛出错误,确保子组件只能在父组件包裹下使用,同时父子组件可以方便地共享状态和方法。
内容的提问来源于stack exchange,提问作者Karthi Keyan
相关产品推荐
相关产品推荐

