javascript - React.cloneElement/HOC/嵌入

标签 javascript reactjs transclusion

我正在使用 React 组合一个表格控件,它几乎一直遵循这种模式一直到单元格:

class Table extends Component {
    static propTypes = {
        tableClass: PropTypes.string,
        columnDefinitions: PropTypes.array.isRequired
    }

    constructor(props) {
        super(props);
    }

    render() {
        const { tableClass, children } = this.props;
        const passthroughProps = except(this.props, ['id', 'key', 'children', 'form', 'tableClass']);
        const transformedChildren = React.Children.map(children, c => React.cloneElement(c, passthroughProps));

        return (
            <div className={ `${ tableClass ? `${tableClass} ` : '' }table` }>
                { transformedChildren }
            </div>
        );
    }
}

export default Table;

except 只是一个实用程序,它获取对象的所有“自己”属性 except ,用于第二个参数中定义的属性(作为属性名称数组)

在你告诉我使用高阶组件之前,让我提供更多细节。我以这种方式设计表格的原因是我希望人们能够使用如下所示的控件(他们可以在其中提供自己的自定义实现)。

<Table columnDefinitions={columnDefinitions}>
    <Row>
        <Cell/>
        <Cell/>
        <Cell/>
    </Row>
    <CustomRow />
</Table>
即使我想放弃类似嵌入的方法 - 我不太确定如何使用高阶组件来做到这一点,因为它们似乎更适合更具确定性的方法。澄清一下,我们有一个 CardCardList 的 HOC:

const CardListHOC = (Card) => CardList extends Component {
    // propTypes, etc...
    render() {
        const { items } = this.props;
        const passthroughProps = except(this.props, ['id', 'key', 'children', 'form', 'items']);

        return (
            {items.map(i => (<div className="card-list-wrapper"><Card {...passthroughProps} item={i}/></div>)}
        );
    }
}

const CardHOC = (Child) => Card extends Component {
    // propTypes, etc...
    render() {
        const passthroughProps = except(this.props, ['id', 'key', 'children', 'form']);

        return (
            <div className="card-wrapper">
                <Child {...passthroughProps} />
            </div>
        );
    }
}

CardListHOC 仅采用单一类型的 Card,因此这意味着我传递给 CardHOCChild 组件code> 必须根据输入数据为我想要支持的所有自定义类型的卡实现所有自定义逻辑。

React.cloneElement 方法的问题是子元素首先渲染,因此在第一次传递时,子元素在“转换”之前没有来自其父元素的 props - 所以你最终会导致效率低下,并且我无法使用 Row 组件,例如,需要 columnDefinitions 作为 Prop ,除非我明确地将它们传递给每个 Row 像这样:

<Table columnDefinitions={columnDefinitions}>
    <Row columnDefinitions={columnDefinitions}>
        <Cell/>
        <Cell/>
        <Cell/>
    </Row columnDefinitions={columnDefinitions}>
    <CustomRow columnDefinitions={columnDefinitions}/>
</Table>

有没有更好的方法来解决这个问题?也许有一种我没有看到的 HOC 方法?如果有人能指出我正确的方向,我将不胜感激!

最佳答案

尽管可能令人惊讶 - 我只不过是昨天 - React Elements 并未使用 React.createElement 进行实例化。 (又名 <Element/> )。你可以尝试一下,只有当元素挂载到 DOM 上时,该类才会实例化。这就是为什么cloneElement效率并不低,这就是为什么子元素在转换之前不会被渲染。

话虽如此,您可能想看看 React context一些魔法粉。

关于javascript - React.cloneElement/HOC/嵌入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36504787/

相关文章:

javascript - HammerJS 事件属性未定义

javascript - JQuery 在运行时从 Checkbox 中检索 id

javascript - 如何使用react-i18next通过不同的javascript文件更改语言?

javascript - Angular : Wrapping an element into a custom template with an angular attribute directive

Angular 遮挡 : X is not a known element

javascript - Ajax、重定向和删除

javascript - 从 Html View 更新触发更新到动态 View ,将其保存到 LocalStorage loki js

android - 使用 React-Native 在 android 中捕获 RECEIVE_BOOT_COMPLETED 事件

reactjs - react-router 错误 pathname.match 不是一个函数

angularjs - angularjs中包含的主要用途是什么