如何制作一个 React.FC 来渲染一个 Ant Design TabPanes 数组?
How to make a React.FC that renders an array of Ant Design TabPanes?
所以,我正在尝试从 Ant Design 渲染一些选项卡(在这里使用 3.x
,就像在我的真实应用程序中一样,但我敢打赌它在 4.x
中完全相同)我需要在我的应用程序的不同部分重用。其中一些选项卡依赖于来自 API 检索的模式的动态数据。根据该数据,选项卡的内容会发生变化,或者某些选项卡甚至不会呈现。
长话短说,我试图用这个片段来简化我的用例。我想要一个 <DynamicTabPanes />
组件,在给定所需数据的情况下能够处理逻辑,并且 return 需要 TabPanes
.
显然,Ant Design 不喜欢这样。如果我像这样使用我的组件:
<Tabs>
<DynamicTabPanes data={someApiData} />
</Tabs>
我收到这些错误:
There must be tab
property on children of Tabs.
但是,当然,如果我为我的组件提供 key
和 tab
属性,antd
将其呈现为简单的 TabPane
。参见:
const { Tabs } = antd;
const { TabPane } = Tabs;
const DynamicTabPanes = ({data}) => {
return data.map((tab, index) => <TabPane tab={tab.label} key={index}>{tab.content}</TabPane>)
}
const someApiData = [{label: "First", content: "First Content"}, {label: "Second", content: "Second Content"}];
ReactDOM.render(
<Tabs>
<TabPane key="static-1" tab="Static Tab">Some static content</TabPane>
<DynamicTabPanes data={someApiData} key="whatever" tab="I don't want this title..."/>
</Tabs>, document.getElementById('root')
);
<link href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.26.20/antd.css" rel="stylesheet"/>
<div id="root"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/3.26.20/antd-with-locales.js" crossorigin="anonymous"></script>
我(有点)使用函数而不是 FC 使其工作,如下所示:
const { Tabs } = antd;
const { TabPane } = Tabs;
const renderDynamicTabPanes = (data) => {
return data.map((tab, index) => <TabPane tab={tab.label} key={index}>{tab.content}</TabPane>)
}
const someApiData = [{label: "First", content: "First Content"}, {label: "Second", content: "Second Content"}];
ReactDOM.render(
<Tabs>
<TabPane key="static-1" tab="Static Tab">Some static content</TabPane>
{renderDynamicTabPanes(someApiData)}
</Tabs>, document.getElementById('root')
);
<link href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.26.20/antd.css" rel="stylesheet"/>
<div id="root"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/3.26.20/antd-with-locales.js" crossorigin="anonymous"></script>
但这似乎不是一个好的解决方案,因为:
- React 应该是关于组件的,而不是插值。
<DynamicTabPanes />
需要使用一些钩子,你不能在非 FC 的函数中使用它们。
关于如何使这项工作有任何想法吗?谢谢!
好的,我做了一些调查,所以我们有以下内容:
- Ant-design 使用 'rc-tabs' 中的
Tabs
和 TabPane
,所有与选项卡渲染相关的逻辑都位于 github src
Tabs
因为包装器组件负责渲染其子组件。
您可以检查 Tabs
组件是否在 parseTabList
函数 src 中迭代它的直接子项。它将您的 DynamicTabPanes
组件检测为单个组件。然后基于直接子项数组的选项卡组件创建导航项 TabNavList
和内容面板列表 TabPanelList
(因此选项卡的数量将与直接子项的数量匹配,在您的示例中为两个)。
- 所以答案是否定的,你不能用你的自定义组件代替其他一些元素。据我所知,您不能在渲染之前用少数元素替换一个元素。
您可以像下面这样创建您自己的窗格并在那里使用您的挂钩(它不再是每个窗格的单独挂钩):
const CustomPane = (props) => {
if (!props.active) {
return <div></div>;
}
return (
<Fragment>
My custom tab
<TabPane {...props}>{props.children}</TabPane>
</Fragment>
);
};
您可以像下面的代码那样做一些事情,但它只是另一种方法,可以像您一样做同样的事情。您还可以将 staticPanel 替换为静态面板的配置数组,并将其与动态连接,然后进行映射。
const DynamicTabPanes = (staticPanes, data) => {
return staticPanes.concat(
data.map((tab, index) => (
<TabPane tab={tab.label} key={index}>
{tab.content}
</TabPane>
))
);
};
function App() {
const someApiData = [
{ label: "First", content: "First Content" },
{ label: "Second", content: "Second Content" },
];
const staticPanes = [
<TabPane key="static-1" tab="Static Tab">
Some static content
</TabPane>,
];
return (
<div className="App">
<Tabs children={DynamicTabPanes(staticPanes, someApiData)} />
</div>
);
}
export default App;
希望它能稍微澄清问题的背景。
所以,我正在尝试从 Ant Design 渲染一些选项卡(在这里使用 3.x
,就像在我的真实应用程序中一样,但我敢打赌它在 4.x
中完全相同)我需要在我的应用程序的不同部分重用。其中一些选项卡依赖于来自 API 检索的模式的动态数据。根据该数据,选项卡的内容会发生变化,或者某些选项卡甚至不会呈现。
长话短说,我试图用这个片段来简化我的用例。我想要一个 <DynamicTabPanes />
组件,在给定所需数据的情况下能够处理逻辑,并且 return 需要 TabPanes
.
显然,Ant Design 不喜欢这样。如果我像这样使用我的组件:
<Tabs>
<DynamicTabPanes data={someApiData} />
</Tabs>
我收到这些错误:
There must be
tab
property on children of Tabs.
但是,当然,如果我为我的组件提供 key
和 tab
属性,antd
将其呈现为简单的 TabPane
。参见:
const { Tabs } = antd;
const { TabPane } = Tabs;
const DynamicTabPanes = ({data}) => {
return data.map((tab, index) => <TabPane tab={tab.label} key={index}>{tab.content}</TabPane>)
}
const someApiData = [{label: "First", content: "First Content"}, {label: "Second", content: "Second Content"}];
ReactDOM.render(
<Tabs>
<TabPane key="static-1" tab="Static Tab">Some static content</TabPane>
<DynamicTabPanes data={someApiData} key="whatever" tab="I don't want this title..."/>
</Tabs>, document.getElementById('root')
);
<link href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.26.20/antd.css" rel="stylesheet"/>
<div id="root"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/3.26.20/antd-with-locales.js" crossorigin="anonymous"></script>
我(有点)使用函数而不是 FC 使其工作,如下所示:
const { Tabs } = antd;
const { TabPane } = Tabs;
const renderDynamicTabPanes = (data) => {
return data.map((tab, index) => <TabPane tab={tab.label} key={index}>{tab.content}</TabPane>)
}
const someApiData = [{label: "First", content: "First Content"}, {label: "Second", content: "Second Content"}];
ReactDOM.render(
<Tabs>
<TabPane key="static-1" tab="Static Tab">Some static content</TabPane>
{renderDynamicTabPanes(someApiData)}
</Tabs>, document.getElementById('root')
);
<link href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.26.20/antd.css" rel="stylesheet"/>
<div id="root"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/3.26.20/antd-with-locales.js" crossorigin="anonymous"></script>
但这似乎不是一个好的解决方案,因为:
- React 应该是关于组件的,而不是插值。
<DynamicTabPanes />
需要使用一些钩子,你不能在非 FC 的函数中使用它们。
关于如何使这项工作有任何想法吗?谢谢!
好的,我做了一些调查,所以我们有以下内容:
- Ant-design 使用 'rc-tabs' 中的
Tabs
和TabPane
,所有与选项卡渲染相关的逻辑都位于 github src Tabs
因为包装器组件负责渲染其子组件。 您可以检查Tabs
组件是否在parseTabList
函数 src 中迭代它的直接子项。它将您的DynamicTabPanes
组件检测为单个组件。然后基于直接子项数组的选项卡组件创建导航项TabNavList
和内容面板列表TabPanelList
(因此选项卡的数量将与直接子项的数量匹配,在您的示例中为两个)。- 所以答案是否定的,你不能用你的自定义组件代替其他一些元素。据我所知,您不能在渲染之前用少数元素替换一个元素。
您可以像下面这样创建您自己的窗格并在那里使用您的挂钩(它不再是每个窗格的单独挂钩):
const CustomPane = (props) => {
if (!props.active) {
return <div></div>;
}
return (
<Fragment>
My custom tab
<TabPane {...props}>{props.children}</TabPane>
</Fragment>
);
};
您可以像下面的代码那样做一些事情,但它只是另一种方法,可以像您一样做同样的事情。您还可以将 staticPanel 替换为静态面板的配置数组,并将其与动态连接,然后进行映射。
const DynamicTabPanes = (staticPanes, data) => {
return staticPanes.concat(
data.map((tab, index) => (
<TabPane tab={tab.label} key={index}>
{tab.content}
</TabPane>
))
);
};
function App() {
const someApiData = [
{ label: "First", content: "First Content" },
{ label: "Second", content: "Second Content" },
];
const staticPanes = [
<TabPane key="static-1" tab="Static Tab">
Some static content
</TabPane>,
];
return (
<div className="App">
<Tabs children={DynamicTabPanes(staticPanes, someApiData)} />
</div>
);
}
export default App;
希望它能稍微澄清问题的背景。