ReactJS中如何渲染宽度小于100px的可见Tabs标签项数组?
错误原因
你通过tabsRef.current.children获取到的是浏览器原生DOM对象,不是React可识别的虚拟节点,直接将这类对象存入状态并渲染就会触发Objects are not valid as a React child报错。
解决方法
不要直接操作存储DOM节点,改为用隐藏测量容器的方式计算每个Tab的宽度,再根据宽度筛选对应React元素渲染,修改后的实现逻辑如下:
1. 修改TabList组件代码
import { useRef, useContext, useEffect, useState } from 'react'; import { TabsContext } from './context'; const TabList = ({ isAlign, isSize, isBoxed, isToggle, isToggleRounded, isFullwidth, children, ...rest }) => { // 测量用容器的ref const measureRef = useRef(null); const { setTabsVisible, setTabsHidden } = useContext(TabsContext); // 存储可见Tab的索引 const [visibleIndexes, setVisibleIndexes] = useState([]); useEffect(() => { if (!measureRef.current) return; const hiddenTabs = []; const visibleTabs = []; const visibleIdx = []; // 遍历测量层节点,顺序和传入的children完全对应 [...measureRef.current.children].forEach((domNode, index) => { const tabElement = children[index]; if (domNode.offsetWidth > 100) { hiddenTabs.push(tabElement); } else { visibleTabs.push(tabElement); visibleIdx.push(index); } }); // 存入context的是React元素,不是DOM节点 setTabsVisible(visibleTabs); setTabsHidden(hiddenTabs); setVisibleIndexes(visibleIdx); }, [children, setTabsVisible, setTabsHidden]); return ( <div> {/* 隐藏测量层:脱离正常文档流,不可见,仅用于计算Tab实际宽度 */} <div ref={measureRef} style={{ position: 'absolute', left: '-9999px', top: '-9999px', visibility: 'hidden' }} > <ul className="tabs"> {children} </ul> </div> {/* 真实渲染的可见Tab列表 */} <ul className="tabs"> {visibleIndexes.map(idx => children[idx])} </ul> </div> ); }; TabList.displayName = "Tabs.TabList"; export { TabList };
2. 配套调整点
- 删除外层传入的
defaultTabsVisible属性,现在可见Tab由宽度动态计算,无需默认传入 - 如果需要支持窗口缩放时重新计算宽度,可在useEffect中添加resize事件监听
- 保证测量层的
ul样式和真实渲染的ul样式完全一致,避免宽度计算偏差
内容的提问来源于stack exchange,提问作者user944513
相关产品推荐
相关产品推荐

