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

使用高阶组件消除React组件代码冗余的方案咨询

更优的React逻辑复用方案推荐

针对你要复用数据获取、加载状态渲染的需求,有几种更符合React组件范式的方案,比你当前的传参函数方案更易于维护和扩展:

1. 标准高阶组件(HOC)

高阶组件的核心是接收一个组件,返回一个新组件,新组件封装复用逻辑,把处理好的数据传递给被包裹的组件,完全贴合你最初想使用HOC的需求:

import { CircularProgress } from "@mui/material";
import React from "react";

function getData(id: number) {
  return id === -1 ? undefined : `Value for ${id}`;
}

// 定义HOC:接收被包裹组件,返回带数据逻辑的新组件
const withData = <P extends { data: string }>(WrappedComponent: React.ComponentType<P>) => {
  return (props: Omit<P, "data"> & { id: number }) => {
    const data = getData(props.id);
    
    if (!data) return <CircularProgress />;
    
    // 把数据传给被包裹组件,同时透传其他props
    return <WrappedComponent {...props as Omit<P, "data">} data={data} />;
  };
};

// 定义仅负责渲染的基础组件
function BaseComponent(props: { data: string; componentName: string }) {
  return <>Showing {props.data} in component {props.componentName}</>;
}

// 生成带数据逻辑的组件
const ComponentA = withData(BaseComponent);
const ComponentB = withData(BaseComponent);

// 使用方式:直接作为组件传入id和其他props
// <ComponentA id={1} componentName="A" />
// <ComponentB id={2} componentName="B" />

这种方案可以快速给多个组件注入数据逻辑,符合React社区对HOC的通用认知。

2. Render Props 组件

Render Props 通过组件的props传递渲染逻辑,灵活性更高,不需要创建新的组件,直接在使用时定义渲染内容:

import { CircularProgress } from "@mui/material";
import React from "react";

function getData(id: number) {
  return id === -1 ? undefined : `Value for ${id}`;
}

// 封装数据逻辑的Render Props组件
const DataLoader = ({ id }: { id: number; children: (data: string) => JSX.Element }) => {
  const data = getData(id);
  
  if (!data) return <CircularProgress />;
  
  return children(data);
};

// 使用方式:直接在JSX中使用,传入id和渲染逻辑
// <DataLoader id={1}>
//   {(data) => <>Showing {data} in component A</>}
// </DataLoader>
// <DataLoader id={2}>
//   {(data) => <>Showing {data} in component B</>}
// </DataLoader>

这种方案适合需要动态调整渲染逻辑的场景,避免了创建过多包装组件。

3. 自定义Hook(推荐)

React Hooks出现后,自定义Hook是复用状态逻辑的首选方案,它更轻量化,且能让组件保留自己的渲染控制权:

import { CircularProgress } from "@mui/material";
import React from "react";

function getData(id: number) {
  return id === -1 ? undefined : `Value for ${id}`;
}

// 自定义Hook:封装数据获取逻辑
function useData(id: number) {
  // 如果是异步数据,可加入useState和useEffect处理,这里同步获取直接返回
  const data = getData(id);
  const isLoading = !data;
  return { data, isLoading };
}

// 使用Hook的组件
function ComponentA(props: { id: number }) {
  const { data, isLoading } = useData(props.id);
  
  if (isLoading) return <CircularProgress />;
  return <>Showing {data} in component A</>;
}

function ComponentB(props: { id: number }) {
  const { data, isLoading } = useData(props.id);
  
  if (isLoading) return <CircularProgress />;
  return <>Showing {data} in component B</>;
}

自定义Hook的优势在于逻辑复用颗粒度更细,组件代码更直观,同时支持异步数据获取(只需在Hook中加入useEffect处理异步请求),扩展性最强。


内容的提问来源于stack exchange,提问作者Maxence Cramet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 11:36:08