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

react-aria中useTabListState相关类型查找及使用疑问求助

为React Aria Tabs组件添加类型定义的问题

我正在测试react-aria的Tabs组件,尝试为其官方示例添加类型定义。问题在于,我不确定Tabs组件的props应使用哪种类型。useTabListState依赖TabListStateOptions类型,但我在相关包中找不到它,查看仓库后发现该类型并未在库中导出。

请问我是否应该使用node_modules中的类型?有没有遗漏的类型查找方法?

当前代码(不含CSS及使用部分)

import {useTab, useTabList, useTabPanel} from 'react-aria';
import {Item, useTabListState} from 'react-stately';

function Tabs(props) {
  let state = useTabListState(props);
  let ref = React.useRef(null);
  let { tabListProps } = useTabList(props, state, ref);
  return (
    <div className={`tabs ${props.orientation || ''}`}>
      <div {...tabListProps} ref={ref}>
        {[...state.collection].map((item) => (
          <Tab
            key={item.key}
            item={item}
            state={state}
            orientation={props.orientation}
          />
        ))}
      </div>
      <TabPanel key={state.selectedItem?.key} state={state} />
    </div>
  );
}

function Tab({ item, state, orientation }) {
  let { key, rendered } = item;
  let ref = React.useRef(null);
  let { tabProps } = useTab({ key }, state, ref);
  return (
    <div {...tabProps} ref={ref}>
      {rendered}
    </div>
  );
}

function TabPanel({ state, ...props }) {
  let ref = React.useRef(null);
  let { tabPanelProps } = useTabPanel(props, state, ref);
  return (
    <div {...tabPanelProps} ref={ref}>
      {state.selectedItem?.props.children}
    </div>
  );
}

解决方法

  • 提取未导出的类型
    利用TypeScript的Parameters工具类型,从useTabListState的参数中直接提取所需类型,无需依赖未导出的TabListStateOptions:

    import { useTabListState } from 'react-stately';
    
    // 提取useTabListState的第一个参数类型
    type TabListStateOptions = Parameters<typeof useTabListState>[0];
    

    直接将此类型用于Tabs组件的props:

    function Tabs(props: TabListStateOptions) {
      // 原有逻辑不变
    }
    
  • 扩展自定义props
    如果需要添加自定义属性(比如额外的className),可以扩展提取到的类型:

    type TabsProps = TabListStateOptions & {
      className?: string;
    };
    
    function Tabs(props: TabsProps) {
      // 原有逻辑不变
    }
    
  • 不建议直接引用node_modules类型
    直接导入node_modules内的类型文件会导致依赖路径不稳定,库版本更新时容易出现类型断裂问题,使用上述类型提取方式更可靠。

  • 补充其他组件的类型
    对于Tab和TabPanel,可以通过ReturnType和类型推导提取所需类型:

    // 提取useTabListState的返回值类型
    type TabListState = ReturnType<typeof useTabListState>;
    // 提取集合中item的类型
    type TabItem = typeof useTabListState extends () => infer S ? S['collection'] extends Iterable<infer I> ? I : never : never;
    

    完整的带类型代码参考:

    import { useTab, useTabList, useTabPanel } from 'react-aria';
    import { Item, useTabListState } from 'react-stately';
    import React from 'react';
    
    type TabListStateOptions = Parameters<typeof useTabListState>[0];
    type TabListState = ReturnType<typeof useTabListState>;
    type TabItem = typeof useTabListState extends () => infer S ? S['collection'] extends Iterable<infer I> ? I : never : never;
    
    type TabsProps = TabListStateOptions;
    
    function Tabs(props: TabsProps) {
      let state = useTabListState(props);
      let ref = React.useRef<HTMLDivElement>(null);
      let { tabListProps } = useTabList(props, state, ref);
      return (
        <div className={`tabs ${props.orientation || ''}`}>
          <div {...tabListProps} ref={ref}>
            {[...state.collection].map((item) => (
              <Tab
                key={item.key}
                item={item}
                state={state}
                orientation={props.orientation}
              />
            ))}
          </div>
          <TabPanel key={state.selectedItem?.key} state={state} />
        </div>
      );
    }
    
    type TabProps = {
      item: TabItem;
      state: TabListState;
      orientation?: TabListStateOptions['orientation'];
    };
    
    function Tab({ item, state, orientation }: TabProps) {
      let { key, rendered } = item;
      let ref = React.useRef<HTMLDivElement>(null);
      let { tabProps } = useTab({ key }, state, ref);
      return (
        <div {...tabProps} ref={ref}>
          {rendered}
        </div>
      );
    }
    
    type TabPanelProps = {
      state: TabListState;
    } & React.HTMLAttributes<HTMLDivElement>;
    
    function TabPanel({ state, ...props }: TabPanelProps) {
      let ref = React.useRef<HTMLDivElement>(null);
      let { tabPanelProps } = useTabPanel(props, state, ref);
      return (
        <div {...tabPanelProps} ref={ref}>
          {state.selectedItem?.props.children}
        </div>
      );
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:54:54