网站搜索

javascript - 维护一个 React 组件列表然后渲染到父组件中


我有一个关于维护多态 React 组件数组的假设性问题。是否可能/是否是良好的 React 做法去维护一个继承自同一公共组件的组件数组,然后在容器中渲染它们?例如:

import * as React from 'react';

import GenericBlock from './GenericBlock';
import { BlockTypeA, BlockTypeB, BlockTypeC } from './MyBlocks';

export default class BlockHolder extends React.Component {
    blocks : GenericBlock[] = [ <BlockTypeA />, <BlockTypeB />, <BlockTypeC /> ];

    render() {
        return (
            <div id="workspace">
                {
                    this.blocks
                }
            </div>);
    };
};

通用块.tsx

import * as React from 'react';

export default class GenericBlock extends React.Component {
    render() { return (<div></div>); }
}

MyBlocks.tsx:

import * as React from 'react';

import GenericBlock from './GenericBlock';

class BlockTypeA extends GenericBlock {
    render() { return (<div></div>); }
};

class BlockTypeB extends GenericBlock {
    render() { return (<div></div>); }
};

class BlockTypeC extends GenericBlock {
    render() { return (<div></div>); }
};

export { BlockTypeA, BlockTypeB, BlockTypeC };

上述代码片段会产生错误:Objects are not valid as a React child,但我认为它捕捉到了我所说内容的精髓。有没有办法让上述方案可行?

我确定这个问题已经被问过并得到回答,但我似乎无法正确使用谷歌搜索。

编辑:

已添加沙箱链接: https://codesandbox.io/s/wizardly-wilson-vb7nn

现在我遇到了一个新错误:类型 'Element' 缺少类型 'GenericBlock' 的以下属性:render、context、setState、forceUpdate,以及另外两个。

编辑 2:

将 blocks 数组类型设为 JSX.Element 可以消除错误并让一切正常工作,但这似乎不是很好的做法,因为 JSX.Element 可以是任何元素,而将其类型设为 GenericBlock 的目的是确保所有元素都是特定组件的子孙组件。

答案#1

在 React 代码中,它运行得非常完美:https://codesandbox.io/s/optimistic-ptolemy-g25ge

无错误,无警告

import * as React from "react";

import { BlockTypeA, BlockTypeB, BlockTypeC } from "./MyBlocks";

export default class BlockHolder extends React.Component {
  blocks = [
    <BlockTypeA key={1} />,
    <BlockTypeB key={2} />,
    <BlockTypeC key={3} />
  ];

  render() {
    return <div id="workspace">{this.blocks}</div>;
  }
}

import * as React from "react";

export default class GenericBlock extends React.Component {
  render() {
    return <div />;
  }
}

import * as React from 'react';

import GenericBlock from './GenericBlock';

class BlockTypeA extends GenericBlock {
    render() { return (<div>A</div>); }
};

class BlockTypeB extends GenericBlock {
    render() { return (<div>B</div>); }
};

class BlockTypeC extends GenericBlock {
    render() { return (<div>C</div>); }
};

export { BlockTypeA, BlockTypeB, BlockTypeC };
"dependencies": {
    "react": "16.12.0",
    "react-dom": "16.12.0",
    "react-scripts": "3.0.1"
  },
  "devDependencies": {
    "typescript": "3.8.3"
  }