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

自定义FilterAccordionTab组件无法渲染内容求助

自定义PrimeReact AccordionTab组件无法渲染内容的问题

问题描述

自定义的FilterAccordionTab组件(继承自PrimeReact V8的AccordionTab)无法渲染内容,但在自定义FilterAccordion组件中直接使用PrimeAccordionTab时,功能完全正常。

代码详情

FilterAccordion.tsx

import React from 'react';
import {
  Accordion as PrimeAccordion,
  AccordionTab as PrimeAccordionTab,
} from 'primereact/accordion';
import {
  AccordionProps as PrimeAccordionProps,
  AccordionTabProps as PrimeAccordionTabProps,
} from 'primereact/accordion';

// 扩展Accordion属性
export interface FilterAccordionProps extends PrimeAccordionProps {
  'data-testid'?: string;
}

// 扩展AccordionTab属性
export interface FilterAccordionTabProps extends PrimeAccordionTabProps {
  'data-testid'?: string;
}

// FilterAccordion组件
export const FilterAccordion: React.FC<FilterAccordionProps> = ({
  children,
  'data-testid': dataTestId,
  ...props
}) => {
  return (
    <PrimeAccordion data-testid={dataTestId} {...props}>
      {children}
    </PrimeAccordion>
  );
};

// FilterAccordionTab组件(原问题版本)
export const FilterAccordionTab: React.FC<FilterAccordionTabProps> = ({
  children,
  'data-testid': dataTestId,
  ...props
}) => {
  return (
    <PrimeAccordionTab data-testid={dataTestId} {...props}>
      {children}
    </PrimeAccordionTab>
  );
};

Storybook示例

import React, { useState } from 'react';
import { Meta, StoryObj } from '@storybook/react';
import {
  FilterAccordion,
  FilterAccordionTab,
  FilterAccordionProps,
} from '..';

type Story = StoryObj<FilterAccordionProps>;

const DefaultTemplate: Story = {
  render: (args) => {
    const [activeIndex, setActiveIndex] = useState<number>(0);

    return (
      <FilterAccordion
        {...args}
        activeIndex={activeIndex}
        onTabChange={(e: any) => setActiveIndex(e.index)}
      >
        <FilterAccordionTab header="Header I">Content I</FilterAccordionTab>
        <FilterAccordionTab header="Header II">Content II</FilterAccordionTab>
        <FilterAccordionTab header="Header III">Content III</FilterAccordionTab>
      </FilterAccordion>
    );
  },
};

export const Default: Story = {
  ...DefaultTemplate,
};

const PlaygroundTemplate: Story = {
  render: (args) => {
    const [activeIndex, setActiveIndex] = useState<number[]>([1, 2]);

    return (
      <FilterAccordion
        {...args}
        activeIndex={activeIndex}
        onTabChange={(e: any) => setActiveIndex([e.index])}
      >
        <FilterAccordionTab header="Header I">Content I</FilterAccordionTab>
        <FilterAccordionTab header="Header II">Content II</FilterAccordionTab>
        <FilterAccordionTab header="Header III">Content III</FilterAccordionTab>
      </FilterAccordion>
    );
  },
};

export const Playground: Story = {
  ...PlaygroundTemplate,
  args: {
    width: '280px',
  },
};

const meta: Meta<FilterAccordionProps> = {
  title: 'Table/Filters/Table Filter Accordion',
  component: FilterAccordion,
  tags: ['autodocs'],
  parameters: {
    docs: {
      description: {
        component: `A 'FilterAccordion' groups a collection of contents in tabs. It consists of one or more FilterAccordionProps elements which are collapsed by default.
        Tab to expand initially can be defined with the activeIndex property.`,
      },
    },
  },
};

export default meta;

问题表现

  • 在FilterAccordion中使用FilterAccordionTab时,标签页无法渲染内容,页面无任何显示
  • 直接在FilterAccordion中使用PrimeAccordionTab时,折叠面板功能完全正常

已尝试方案

  • 验证FilterAccordion和FilterAccordionTab的children传递逻辑正确
  • 对比FilterAccordionTab与PrimeAccordionTab的结构和属性定义,未发现差异
  • 添加控制台日志排查渲染流程,但无相关日志输出

预期与实际行为

  • 预期:FilterAccordionTab应与PrimeAccordionTab完全一致,正常渲染标签页内容
  • 实际:FilterAccordionTab在FilterAccordion中无法渲染任何内容

解决思路与建议

核心原因

PrimeReact的Accordion组件内部会通过组件类型或displayName识别子组件是否为AccordionTab,同时部分组件依赖ref进行内部状态管理。自定义的FilterAccordionTab作为包裹组件,会被识别为普通React组件,而非Prime原生的AccordionTab,导致Accordion无法正确处理子组件的渲染逻辑。

具体修复步骤

  1. 使用React.forwardRef传递Ref
    PrimeReact的AccordionTab组件依赖ref进行DOM操作和状态管理,原代码使用React.FC无法传递ref,需改用forwardRef:

    export const FilterAccordionTab = React.forwardRef<PrimeAccordionTab, FilterAccordionTabProps>(
      ({ children, 'data-testid': dataTestId, ...props }, ref) => {
        return (
          <PrimeAccordionTab ref={ref} data-testid={dataTestId} {...props}>
            {children}
          </PrimeAccordionTab>
        );
      }
    );
    
  2. 设置与原生组件一致的displayName
    给自定义组件设置和PrimeAccordionTab相同的displayName,让Accordion能识别它是合法的子组件:

    FilterAccordionTab.displayName = 'AccordionTab';
    
  3. 完整修复后的FilterAccordionTab代码

    // FilterAccordionTab组件(修复后)
    export const FilterAccordionTab = React.forwardRef<PrimeAccordionTab, FilterAccordionTabProps>(
      ({ children, 'data-testid': dataTestId, ...props }, ref) => {
        return (
          <PrimeAccordionTab ref={ref} data-testid={dataTestId} {...props}>
            {children}
          </PrimeAccordionTab>
        );
      }
    );
    FilterAccordionTab.displayName = 'AccordionTab';
    

验证方法

修改后重新运行Storybook,检查FilterAccordionTab是否能正常渲染内容,折叠/展开功能是否正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 11:40:11