You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:24:53