【问题标题】:Embedded expression rendering as array instead of individual elements嵌入式表达式呈现为数组而不是单个元素
【发布时间】:2017-12-20 14:38:18
【问题描述】:

我有以下嵌套组件:

<Table data={records}>
    <TableColumn field="code">Code</TableColumn>
    {columns.map((column, i) => (
      <TableColumn key={column} field={column}>
        {column}
      </TableColumn>
    ))}
</Table>

我的Table 组件扩展了这个接口:

export interface TableProps {
  data: any[];
  children: React.ReactElement<TableColumnProps>[];
}

在该组件中,我使用以下函数遍历 Table 的子项(TableColumn 的实例):

getDefaultSortColumn() {
    let col = this.props.children[0].props.field;
    this.props.children.forEach((column: React.ReactElement<TableColumnProps>) => {
      if (column.props.sortDefault) {
        col = column.props.field;
      }
    });
    return col as string;
  }

当它执行时,我的期望是带有map() 的JSX 表达式已经执行,如果columns 中有4 个项目,那么在我的Table 中将有5 个TableColumn 元素作为直接子元素。相反,第二个元素实际上是一个元素数组。

为什么我的代码不只将TableColumn 元素作为直接子元素呈现给我的Table

更新 似乎做以下工作:

  getDefaultSortColumn() {
    let col = this.props.children[0].props.field;
    this.props.children.forEach((child: React.ReactElement<any>) => {
      if (Array.isArray(child)) {
        child.forEach((column: React.ReactElement<O3TableColumnProps>) => {
          if (column.props.sortDefault) {
            col = column.props.field;
          }
        });
      }
      else if (child.props.sortDefault) {
        col = child.props.field;
      }
    });
    return col as string;
  }

但我不想像这样访问我的孩子,测试该项目是我想要的TableColumnProps 元素类型还是TableColumnProps 元素的数组。问题依然存在。

【问题讨论】:

    标签: javascript reactjs typescript jsx


    【解决方案1】:

    您的 JSX 编译为如下所示:

    const TableColumn = React.createElement('div', { field: 'code' }, 'Code')
    const Table = React.createElement('div', {}, [
      TableColumn,
      columns.map((column, i) =>
        React.createElement('div', { key: column, field: column }, column),
      ),
    ])
    

    您可以看到Table 的子元素包括一个反应元素和一个反应元素数组。直接遍历 children 数组就可以了。

    React 为这种事情提供了一个顶级 api -- React.Children -- 在你的迭代中使用 React.Children.mapReact.Children.forEach 遍历子数组。

    调整后的函数如下所示:

    getDefaultSortColumn() {
      let col = this.props.children[0].props.field;
      React.Children.forEach(this.props.children, (column) => {
        if (column.props.sortDefault) {
          col = column.props.field;
        }
      });
      return col;
    }
    

    【讨论】:

    • 这会导致以下错误:Argument of type '(column: ReactElement&lt;any&gt;) =&gt; void' is not assignable to parameter of type '(child: ReactChild, index: number) =&gt; any'. Types of parameters 'column' and 'child' are incompatible. Type 'ReactChild' is not assignable to type 'ReactElement&lt;any&gt;'. Type 'string' is not assignable to type 'ReactElement&lt;any&gt;'
    • 除了类型检查之外,答案仍然有效,并且是在 React 中循环子项而无需检查嵌套数组的首选/推荐方法。我将更新答案以排除类型检查位,并让您弄清楚那部分。例如,请参见此处:codesandbox.io/s/jvxqvw3813
    • 你是对的。我能够解决我的类型检查问题,它现在似乎可以工作了。感谢您的澄清!
    猜你喜欢
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 2018-12-30
    • 2016-10-12
    • 1970-01-01
    相关资源
    最近更新 更多