使用额外的 props 将 React 组件分配给变量

Aus*_*ght 2 javascript reactjs

我正在开发一个组件映射函数,该函数循环遍历具有键的对象列表type。该函数返回一个React组件类型的对象,它看起来像这样:

import _ from 'lodash';
import cellBodyTypes from './cellBodyTypes';
import {
    GenericCellBody,
    SubData
} from './components/CellBody';

const columnMapper = {};

_.forEach(cellBodyTypes, (type) => {
    switch (type) {
        case cellBodyTypes.SUB_DATA:
            columnMapper[type] = SubData;
            break;
        case cellBodyTypes.DEFAULT:
            columnMapper[type] = GenericCellBody;
            break;
        default:
            columnMapper[type] = GenericCellBody;
    }
});

export default columnMapper;
Run Code Online (Sandbox Code Playgroud)

它的用法如下:

renderCellBody = (columnType, cellData, index) => {
    const type = columnType || cellBodyTypes.DEFAULT;
    const CellBodyComponent = columnMapper[type];

    return <CellBodyComponent />;
}
Run Code Online (Sandbox Code Playgroud)

渲染看起来像这样:

render (
    <div>
        {this.props.cellData.map((cell, index) => (
            <div key={cell.id}>
                {this.renderCellBody(cell.type, cell, index)}
            </div>
        ))}
    </div>
);
Run Code Online (Sandbox Code Playgroud)

我想要做的是能够为新案例分配列类型,这些新案例使用与其他案例相同的 React 组件,但用额外的 props 装饰这些新列类型。就像是:

case cellBodyTypes.NUMBER_SUB_DATA:
    columnMapper[type] = React.cloneElement(SubData, {someAdditionalProp: 'something'});
    break;
case cellBodyTypes.SINGLE_NUMBER:
    columnMapper[type] = React.cloneElement(GenericCellBody, {someAdditionalProp: 'something'});
    break;
Run Code Online (Sandbox Code Playgroud)

我尝试使用返回 React 组件的克隆,React.cloneElement但这不起作用,因为它给了我这个错误:React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

有没有办法做到这一点?我是否接近正确的道路,只是错过了一些东西?谢谢。

Pra*_*rma 5

那是因为React.cloneElement返回一个反应元素,而不是组件。所以之后

columnMapper[type] = React.cloneElement(SubData,...,

columnMapper[type]将包含一个元素。

但问题是,在renderCellBody函数中,您试图通过编写将元素再次转换为元素

return <CellBodyComponent />;
Run Code Online (Sandbox Code Playgroud)

这会引发错误。

我建议你保留columnMapper一个数组elements。所以switch/case代码应该是这样的

_.forEach(cellBodyTypes, (type) => {
    switch (type) {
        case cellBodyTypes.SUB_DATA:
            // Store element instead of component
            columnMapper[type] = <SubData />;
            break;
        case cellBodyTypes.DEFAULT:
            // Store element instead of component
            columnMapper[type] = <GenericCellBody />;
            break;
        case cellBodyTypes.NUMBER_SUB_DATA:
            columnMapper[type] = React.cloneElement(SubData, {someAdditionalProp: 'something'});
            break;
        case cellBodyTypes.SINGLE_NUMBER:
            columnMapper[type] = React.cloneElement(GenericCellBody, {someAdditionalProp: 'something'});
            break;
        default:
            columnMapper[type] = <GenericCellBody />;
    }
});
Run Code Online (Sandbox Code Playgroud)

所以现在columnMapper是一个数组elements。因此在renderCellBody功能上,你不需要element再次将它们转换成。您可以简单地返回值

renderCellBody = (columnType, cellData, index) => {
    const type = columnType || cellBodyTypes.DEFAULT;
    const CellBodyComponent = columnMapper[type];

    // CellBodyComponent is already an element. So directly return it.
    return CellBodyComponent;
}
Run Code Online (Sandbox Code Playgroud)