Учебник ReactJS (tic tac), создающий блок неожиданной ошибки токена HTML

Ответ, который пытается сделать то же самое со мной: https://stackoverflow.com/a/45785715/8126531

Привет, я делаю учебник по ReactJS здесь, и я в основном в той части, где он просит заменить:

render() {
    return (
      <div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

с 2 петлями, чтобы сделать квадраты вместо жесткого кодирования.

Концептуально, я не знаю, ошибся ли я, но я пытался поместить все элементы в массив, а затем отобразить его следующим образом:

render() {
    return (
        <div>{ this.createBoard(3, 3) }</div>
    );
}

createBoard(rows, columns) {
    let htmlBlock = [];
    for (let i = 0; i < columns; i++) {
        htmlBlock.push(<div className="board-row">);
        for (let j = 0; j < rows; j++) {
            htmlBlock.push(this.renderSquare(j));
        }
        htmlBlock.push(</div>);
    }
    return htmlBlock;
}

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

Может ли кто-нибудь сказать мне, почему у меня эта ошибка, или если я концептуально ошибся, и я должен делать это по-другому?

Ваше здоровье.

Кстати, не уверен, что это актуально, но я использую веб-пакет, и файлы jsx передаются и упаковываются.

[РЕШЕНО]: Всем спасибо за ответы. Благодаря пользователю "emma" мне удалось заставить его работать. Я думаю, проблема в том, что вы не можете поместить "неполный" HTML-блок в массив и отобразить его. Ниже приведены изменения, которые я сделал:

createBoard(rows, columns) {
    let htmlBlock = [];
    for (let i = 0; i < columns; i++) {
        // htmlBlock.push(<div className="board-row">);
        let test = [];
        for (let j = 0; j < rows; j++) {
            test.push(this.renderSquare(j));
        }
        htmlBlock.push(<div> { test }</div>);
    }
    return htmlBlock;
}

Еще раз спасибо ребята!!


person Community    schedule 03.11.2017    source источник


Ответы (4)


Вы не можете нажать <div> и </div> по отдельности. Вместо этого вы должны создать еще один список row внутри верхнего цикла, а затем, когда все будет добавлено в строку, вы можете переместить <div>{row}</div> в htmlBlock.

person emma    schedule 03.11.2017
comment
Большое спасибо!! Ты жжешь! Я сделал то, что вы сказали, и это работает. Я предполагаю, что урок на вынос заключается в том, что вы не можете поместить частично завершенные элементы div в массив и отобразить их. Я добавил правку в свой основной пост, чтобы показать обновленный код, еще раз спасибо, чувак. - person ; 03.11.2017

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

class Board extends React.Component {

  createCells(cols) {
    const result = [];

    for (let i = 0; i < cols; i++) {
      result.push(<div key={"col-" + i} className="column">Cell</div>)
    }

    return result;
  }

  createBoard(rows, cols) {
    const result = [];

    for (let i = 0; i < rows; i++) {
      result.push(<div key={"row-" + i} className="row">{this.createCells(cols)}</div>)
    }

    return result;
  }

  render() {
    return (
        <div className="board">
          { this.createBoard(3, 3) }
        </div>
      )
   }
}

Кстати, никогда не забывайте об атрибуте 'key' при рендеринге массивов в реакции.

person Taras Polovyi    schedule 03.11.2017

Поскольку JSX допускает только выражения, а циклы for не являются выражениями, их немного неудобно использовать вместе с JSX.

Вы можете создавать массивы, заполненные нулевым значением, и вместо этого отображать их, например:

function emptyArray(n) {
  return new Array(n).fill();
}

class Board extends React.Component {
    createBoard(rows, columns) {
        return emptyArray(rows).map((_, i) => (
            <div key={i} className="board-row">
                {emptyArray(columns).map((_, j) => (
                    <span key={j} className="board-column">
                        - row {i + 1}, column {j + 1} -
                    </span>
                ))}
            </div>
        ));
    }

    render() {
        return (
            <div className="board">
                { this.createBoard(3, 3) }
            </div>
        )
   }
}
person Erik Inkapööl    schedule 03.11.2017

Вы можете использовать свойство reactjs dangerouslySetInnerHTML

render() {
    return (
        <div dangerouslySetInnerHTML={{ __html: this.createBoard(3, 3) }}></div>
    );
}

Теперь вы можете использовать строку при отправке строки html в переменную htmlBlock.

person Galih Akbar Moerbayaksa    schedule 03.11.2017
comment
Спасибо за ваш ответ, я хотел бы знать, какова наилучшая практика. - person ; 03.11.2017