首页 > 解决方案 > React App - render() - map () - 使用 if-else 条件映射

问题描述

我创建了我的 ReactApp,并希望显示一个包含来自 AWS dynamodb 的数据的表。

我通过 ReactApp 的 render() 中的 map() 成功地将 dynamodb 中的数据通过 json 传输到 ReactApp,我显示的表格如下:

现在的样子

所以现在我需要重新分配表格,如下所示:

我希望它如何显示

所以我计划相应地使用 if-else 语句来渲染表格:但是一旦我在函数中放入 if-else 子句,它就不起作用并且什么都没有显示。所以想向stackoverflow专家寻求建议:)非常感谢

这是我的代码,我卡住的部分在 render() 的返回部分:

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      hits: [],
      isLoading: false,
      error: null,
    };
  }

  render() {
    const { hits, isLoading, error } = this.state;

    if (error) {
      return <p>{error.message}</p>;
    }

    if (isLoading) {
      return <p>Loading ...</p>;
    }

    return (
      <form>
        <div className="container border border-secondary rounded center">
          <div className="row">
            <div className="col-12">
              {' '}
              <h4>
                <b>Class Mapping</b>
              </h4>{' '}
            </div>
          </div>

          <div className=".col-xs-12 center text-center">
            <Table responsive striped bordered hover>
              <tr>
                <th>Class 1</th>
                <th>Class 2</th>
                <th>Class 3</th>
                <th>Class 4</th>
                <th>Class 5</th>
              </tr>

              <tbody>
                {hits.map((hit) => {
                  if (hit.class === 'Class 1') {
                    <tr>
                      <td>{hit.name}}</td> <td></td> <td></td> <td></td> <td></td>{' '}
                    </tr>;
                  } else if (hit.class === 'Class 2') {
                    <tr>
                      <td></td>
                      <td>{hit.name}}</td> <td></td> <td></td> <td></td>{' '}
                    </tr>;
                  }
                })}
              </tbody>
            </Table>
          </div>
        </div>
      </form>
    );
  }

  async componentDidMount() {
    this.setState({ isLoading: true });
    const response = await fetch('https://xxxxxxx');
    const body = await response.json();
    this.setState({ hits: body, isLoading: false, error: null });
  }
}
export default App;

标签: reactjsdictionaryjsx

解决方案


所以你想要一个看起来像这样的数组:

const hits = [
  { name: 'Tammy', class: 'Class 1' },
  { name: 'Sarah', class: 'Class 2' },
  { name: 'Roland', class: 'Class 3' },
  { name: 'Moshe', class: 'Class 4' },
  { name: 'Peter', class: 'Class 5' },
];

并将其转换为名称数组,按类名排列成列,如下所示:

const rows = [
  ['Tammy', 'Sarah', 'Roland', 'Moshe', 'Peter'],
  ['Helen', 'Eric', 'Fiona', 'Darren', 'Andy'],
];

这将需要一些工作。我不认为你将能够在几个地图函数中使用 if/else 语句来完成它。

让我们试试这个。我建议向您的组件添加一个名为 getRows 的类方法。此方法将进行转换。我们首先遍历您hits的名称并按类对名称进行分组。

然后我们设置一个 while 循环,将名称推送到新的行数组中。虽然我们还有名字,但请继续构建行。每行将根据列选择一个名称并插入它。

最后,当我们都没有名字时,我们可以将行返回给渲染函数。然后我们映射行,并映射每行中的列。我们还需要每个映射元素的唯一键。

获取行()

const getRows = () => {
  const columns = ['Class 1', 'Class 2', 'Class 3', 'Class 4', 'Class 5'];
  const rows = [];

  const groupByColumn = this.state.hits.reduce((acc, next) => {
    return { ...acc, [next.class]: [...(acc[next.class] || []), next.name] };
  }, {});

  const haveNames = () => columns.some((column) => (groupByColumn[column] || []).length > 0);

  while (haveNames()) {
    const newRow = columns.map((column) => {
      return (groupByColumn[column] || []).shift() || '';
    });

    rows.push(newRow);
  }

  return rows;
};

完整的组件:

import React, { Component } from 'react';

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      hits: [],
      isLoading: false,
      error: null,
    };
  }

  async componentDidMount() {
    this.setState({ isLoading: true });
    const response = await fetch('https://xxxxxxx');
    const body = await response.json();
    this.setState({ hits: body, isLoading: false, error: null });
  }

  getRows = () => {
    const columns = ['Class 1', 'Class 2', 'Class 3', 'Class 4', 'Class 5'];
    const rows = [];
  
    const groupByColumn = this.state.hits.reduce((acc, next) => {
      return { ...acc, [next.class]: [...(acc[next.class] || []), next.name] };
    }, {});
  
    const haveNames = () => columns.some((column) => (groupByColumn[column] || []).length > 0);
  
    while (haveNames()) {
      const newRow = columns.map((column) => {
        return (groupByColumn[column] || []).shift() || '';
      });
  
      rows.push(newRow);
    }
  
    return rows;
  };

  render() {
    if (this.state.error) {
      return <p>{error.message}</p>;
    }

    if (this.state.isLoading) {
      return <p>Loading ...</p>;
    }

    return (
      <form>
        <div className="container border border-secondary rounded center">
          <div className="row">
            <div className="col-12">
              {' '}
              <h4>
                <b>Class Mapping</b>
              </h4>{' '}
            </div>
          </div>

          <div className=".col-xs-12 center text-center">
            <Table responsive striped bordered hover>
              <tr>
                <th>Class 1</th>
                <th>Class 2</th>
                <th>Class 3</th>
                <th>Class 4</th>
                <th>Class 5</th>
              </tr>
              <tbody>
                {this.getRows().map((row) => (
                  <tr key={row.reduce((a, b) => a + b)}>
                    {row.map((column) => (
                      <td key={column}>{column}</td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </Table>
          </div>
        </div>
      </form>
    );
  }
}

export default App;

示例代码

const hits = [
  { name: 'Tammy', class: 'Class 1' },
  { name: 'Camen', class: 'Class 2' },
  { name: 'Happy', class: 'Class 3' },
  { name: 'Hello Kitty', class: 'Class 4' },
  { name: 'Hello Mimi', class: 'Class 3' },
];

const getRows = (hits) => {
  const columns = ['Class 1', 'Class 2', 'Class 3', 'Class 4', 'Class 5'];
  const rows = [];

  const groupByColumn = hits.reduce((acc, next) => {
    return { ...acc, [next.class]: [...(acc[next.class] || []), next.name] };
  }, {});

  const haveNames = () => columns.some((column) => (groupByColumn[column] || []).length > 0);

  while (haveNames()) {
    const newRow = columns.map((column) => {
      return (groupByColumn[column] || []).shift() || '';
    });

    rows.push(newRow);
  }

  return rows;
};

const rows = getRows(hits);
console.log(rows);


推荐阅读