将React组件分配给具有额外props的变量

时间:2018-03-05 18:55:44

标签: 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;

它的使用方式如下:

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

    return <CellBodyComponent />;
}

渲染看起来像:

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

我想要做的是能够为使用与其他情况相同的React组件的新案例分配列类型,但是使用其他道具装饰这些新列类型。类似的东西:

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;

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

有办法做到这一点吗?我接近正确的道路,只是遗漏了什么?感谢。

1 个答案:

答案 0 :(得分:2)

这是因为React.cloneElement返回的是反应元素,而不是组件。所以

之后

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

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

但问题是在renderCellBody函数中,您试图通过编写

将元素再次转换为元素
return <CellBodyComponent />;

这会引发错误。

我建议你保留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 />;
    }
});

所以现在columnMapperelements的数组。因此,在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;
}