如何在 React.cloneElement 中获取给定反应组件的文本元素?

How to get text element of the given react component in React.cloneElement?

开发人员给我table的标题:

const CustomersTable = () => {

    var headers=<>
        <th>Name</th>
        <th>Age</th>
        <th>Another text</th>
    </>

    return <Table
               headers={headers}
           />
}

这是 Table 组件的代码:

const Table = ({headers}) => {

    var clonedHeaders = React.Children
            .toArray(headers.props.children)
            .map(header => React.cloneElement(header, {
                className: "text-gray-900 py-3 font-light text-xs"
            }));

    return <table>
         <thead>
            <tr>
                {clonedHeaders}
            </tr>
         </thead>
    </table>
}

我可以使用 React.cloneElement 将属性添加到我收到的作为组件道具的元素。

但是,我也希望能够更改那些接收到的元素的文本内容。

例如,我想在 table header 元素上调用我的 locale 翻译函数自动 .现在,如果开发人员想要制作他们的 tables multi-lingual,他们应该这样写:

var headers = <>
    <th>{t('Name')}</th>
    <th>{t('Age')}</th>
    <th>{t('Other text')}</th>
</>

我想集中所有 headers 道具的 t(text) 功能。我可以这样做吗?

您可以对 headers 的 child 元素使用与对 headers 本身相同的技术:

const clonedHeaders = React.Children
        .toArray(headers.props.children)
        .map(header => React.cloneElement(header, {
            className: "text-gray-900 py-3 font-light text-xs",
            children: React.Children.toArray(header.props.children).map(child => {
                return typeof child === "string" ? t(child) : child;
            })
        }));

实例:

const {useState} = React;

function t(english) {
    // Just so we can see that it happens
    return english.toLocaleUpperCase();
}

const CustomersTable = () => {

    var headers=<React.Fragment>
        <th>Name</th>
        <th>Age</th>
        <th>Another text</th>
    </React.Fragment>;

    return <Table
               headers={headers}
           />;
};

const Table = ({headers}) => {

    const clonedHeaders = React.Children
            .toArray(headers.props.children)
            .map(header => React.cloneElement(header, {
                className: "text-gray-900 py-3 font-light text-xs",
                children: React.Children.toArray(header.props.children).map(child => {
                    return typeof child === "string" ? t(child) : child;
                })
            }));

    return <table>
         <thead>
            <tr>
                {clonedHeaders}
            </tr>
         </thead>
    </table>;
};

ReactDOM.render(<CustomersTable />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

该示例不执行任何递归,因此它不会处理 <th><span className="something">Name</span></th>。如果你想处理它,你必须编写一个递归函数来处理它,但它会沿着相同的路线。