循环遍历React Children的每个嵌套子项



我正在尝试创建一个表组件,该组件将为其特定的子级提供一些特殊的className。

const BasicTable = ({ children }) => {
const RenderChild = Children.map(children, (el) => {
const child = el;

if (child !== null) {
if (child.props.originalType !== "th") {
return <child.type {...child.props} className="th" />;
}

return <child.type {...child.props} />;
}
return null;
});

return (
<div className="table-responsive">
<table className="table w-full bg-transparent">{RenderChild}</table>
</div>
);
};

这是我的组件,我想这样使用它。

<BasicTable>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Position</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>dsfa</td>
<td>dsfa</td>
<td>dsfa</td>
<td>dsfa</td>
</tr>
</tbody>
</BasicTable>

但这里的问题是我的Children.map函数只循环通过它的直接子函数。如何将道具传递给其嵌套的子项(th,td,…等(

您可以定义一个递归函数来迭代所有子级,直到该子级为null或类型为string或根据您的需求满足任何其他条件,这里有一个示例:

const BasicTable = ({ children }) => {
const iterateOverChildren = (children) => {
return React.Children.map(children, (child) => {
// equal to (if (child == null || typeof child == 'string'))
if (!React.isValidElement(child)) return child;
return React.cloneElement(child, {
...child.props,
// you can alse read child original className by child.props.className
className: child.type == 'th' ? 'th' : '',
children: iterateOverChildren(child.props.children)})
})
};
return (
<div className="table-responsive">
<table className="table w-full bg-transparent">
{iterateOverChildren(children)}
</table>
</div>
);
};
function App() {
return (
<BasicTable>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Position</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>dsfa</td>
<td>dsfa</td>
<td>dsfa</td>
<td>dsfa</td>
</tr>
</tbody>
</BasicTable>
);
}

ReactDOM.render(<App/>, document.getElementById('root'))
.th{
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>

您可以在将classNames应用于当前child之后提供children道具。您可以根据需要定义另一个函数来应用自定义类名(逻辑可以根据需要更改(。

这也是可行的。

import { Children, isValidElement } from "react";
const BasicTable = ({ children }) => {
const RenderChild = (children) => {
return Children.map(children, (child) => {
if (isValidElement(child)) {
return (
<child.type
{...child.props}
children={RenderChild(child.props.children)}
className={resolveCalssName(child.type)}
/>
);
}
// non react elements (text inside the table ...etc)
return child;
});
};
const resolveCalssName = (type) => {
switch (type) {
case "thead":
return "custom-thead-class-name";
case "tbody":
return "custom-tbody-class-name";
case "tr":
return "custom-tr-class-name";
case "th":
return "custom-th-class-name";
case "td":
return "custom-td-class-name";
default:
return "";
}
};
return (
<div className="table-responsive">
<table className="table w-full bg-transparent">
{RenderChild(children)}
</table>
</div>
);
};

代码沙盒

最新更新