Передача объекта массивов в качестве реквизита в React, затем использование циклов для создания таблицы с данными

#reactjs

#reactjs

Вопрос:

Объект:

 let skillObj1 = {
      levels: [1, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15, 16, 18, 19, 20, 22, 25, 29, 30, 32, 34, 35, 38],
      skills: [['axe', 'dagger', 'flail', 'polearm', 'spear', 'sword', 'archery', 'whip', 'evaluation', 'enhanced damage', 'staff', 'parry', 'rescue', 'recall'], ['dirt kicking'], ['hand to hand', 'second attack'],
      ['fast healing'], ['kick'], ['trip'], ['shield block'], ['dual wield', 'bash'], ['dodge'], ['haggle', 'lunge'], ['lash', 'disarm'], ['crush', 'warcry', 'meditation'],
      ['shield cleave', 'berserk'], ['third attack'], ['recovery'], ['dual parry', 'pugil'], ['counter'], ['ground control', 'defend'],
      ['fourth attack'], ['battle tactics'], ['enhanced damage II'], ['enlist'], ['block retreat']]
    };
  

Цикл, который я хотел бы использовать, но, очевидно, неверен:

 tableData(props) {
    let data = '';
    for (var i = 0; i < this.props.levels.length; i  ) {
      data.concat('<tr><td>Level '   props.levels[i]   '</td>');
      for (var j = 0; j < props.skills[i].length; j  ) {

        if (j % 2 === 0) {
          data.concat('<td>'   props.skills[i][j]   '</td</tr>');
          if (j !== props.skills[i].length - 1) { data.concat('<tr><td></td>');}
        } else {
          data.concat('<td>'   props.skills[i][j]   '</td>');
          if (j === props.skills[i].length - 1) {data.concat('<td></td></tr>');}
        }

      }
    }
    return data;
  };
  

Мой рендеринг:

 render() {
  return (
    <Table striped bordered hover variant="dark">
      <thead>
        <tr>
          <th><strong>Your list of skills:</strong></th>
          <th></th>
          <th></th>
        </tr>
      </thead>
      <tbody>
      {this.tableData}
      </tbody>
    </Table>
  );
  }
  

Чего я пытаюсь достичь:

Я хочу создать таблицу с 3 столбцами, то есть по 3 <td> в строке. В первом <td> будет уровень, на котором приобретается способность. Это будет показано только в первой строке, где начинаются возможности для этого уровня. Все последовательные строки будут иметь первое <td> пустое место до достижения записей следующего уровня. Фактические возможности будут только во 2-м и 3-м столбцах / <td> -х.

Вроде как это, извините, если это плохой пример:

 |-----|-----|-----|
|Lvl1 | axe |sword|
|-----|flail|-----|
|Lvl2 |kick |trip |
|-----|punch|smell|
|-----|slap |-----|
|Lvl5 |-----|-----|
  

Редактировать:

Я вижу много людей, использующих методы .map() и .filter() для обработки подобных вещей, но моя проблема в том, что у меня есть несколько условий, с которыми я не уверен, как справиться.

Если я попытаюсь просто распечатать массив, <td> с .map() ним все будет хорошо, но либо мои навыки JavaScript / jsx сейчас просто плохи, либо есть лучший способ справиться с условиями, чтобы он печатался в формате, который я ищу.

Правка2

Теперь я пытаюсь заставить что-то подобное работать в рендеринге:

 let levels = this.props.skills.levels;
let skills = this.props.skills.skills;
{levels.map(function(obj, i) {
    return (
        <tr><td>Level {obj}</td>
        skills[i].map(function(obj2, j) {
            if (j % 2 === 0) {
                <TableData skill={obj2[i][j]} /></tr>
                if (j !== obj2[i].length - 1) { <tr><TableData /> }
            } else {
                <TableData skill={obj2[i][j]} /></td>;
                if (j === props.skills[i].length - 1) {<TableData /></tr>}
            }
        });
    )
)}
  

Редактировать 3

Я подумал, что, возможно, троичный оператор может быть подходящим. Я все еще получаю много ошибок jsx, потому что элементы jsx не закрыты «должным образом», хотя цель оператора — закрыть их.

 {levels.map(function(obj, i) {
    return (<tr><td>Level {obj}</td>
            skills[i].map(function(obj2, j) {
              (j % 2 === 0) ?
                (j !== obj2[i][j].length - 1) ? (<TableData skill={obj2[i][j]} /></tr><tr><TableData />) : (<TableData skill={obj2[i][j]} /></tr>)
                : (j === obj2[i].length - 1) ? (<TableData skill={obj2[i][j]} /></td><TableData /></tr>) : (<TableData skill={obj2[i][j]} /></td>);
            });
          )
  )}
  

Редактировать 4 Приближается

   tableData(props) {
    let levels = this.props.skills.levels;
    let skills = this.props.skills.skills;
    let data = [];
for (var i = 0; i < levels.length; i  ) {
      //<tr>beginning
      data.push(<Level level={i} key={i * 100} />);
      for (var j = 0; j <= skills[i].length; j  ) {

        if (j % 2 === 0) {
          data.push(<TableData skill={skills[i][j]} key={i   j} />); //</tr> end
          if (j !== skills[i].length - 1) { data.push(<TableData key={(i   j) * 200} />);}//<tr> beginning
        } else {
          data.push(<TableData skill={skills[i][j]} key={i   j} />);
          if (j === skills[i].length - 1) {data.push(<TableData key={(i   j) * 100} />)} //</tr> end
        }

      }
    }
    return data;
  };
  

С помощью этой функции я могу печатать все в тегах данных таблицы. Однако я все еще не могу поместить теги строк таблицы туда, куда им нужно. Если я не закрываю теги, я получаю ошибку jsx, даже если конечный результат теоретически должен быть правильным.

Комментарии:

1. Предполагается, что каждый массив в навыках соответствует уровню?

2. @Yatrix Да, индекс каждого уровня соответствует индексу массива внутри массива навыков. Таким образом, уровень 1 с индексом 0 соответствует [‘axe’, ‘dagger’, ‘flail’, …], который также является индексом 0 навыков.

3. Итак, в первом <td> есть уровень, во втором td есть навыки, но что должно быть в третьем td?

4. Что-то вроде этого codesandbox.io/s/headless-cdn-vgqfx ?

5. Рад, если бы я мог помочь :). Я опубликовал свой ответ, поэтому вы можете пометить его как решение

Ответ №1:

На мой взгляд, лучший способ — сначала структурировать данные, а затем отобразить их позже, чтобы вам не приходилось возиться с закрывающими тегами и т.д. Вы могли бы использовать цикл for и выполнять итерации по каждому 2 элементу для создания таблицы.

 <div className="App">
      <table>
        <tbody>
          {levels.map((item, i) => {
            var skl = [];
            for (let j = 0; j < skills[i].length; j = j   2) {
              if (j < 2) {
                skl.push(
                  <tr>
                    <td>Level {item}</td>
                    <td>{skills[i][0]}</td>
                    <td>{skills[i][1]}</td>
                  </tr>
                );
              } else {
                skl.push(
                  <tr>
                    <td></td>
                    <td>{skills[i][j]}</td>
                    <td>{skills[i][j   1]}</td>
                  </tr>
                );
              }
            }
            return (
              <React.Fragment>
                {skl.map((item) => {
                  return item;
                })}
              </React.Fragment>
            );
          })}
        </tbody>
      </table>
    </div>
  

https://codesandbox.io/s/headless-cdn-vgqfx