Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concatenating JSX fragments with HTML and then rendering the accumulated result

I'm trying to rewrite Board to use two loops to make the squares instead of hardcoding them. I've tried to concatenate these jsx fragments, I can't just append them like I would be able to if they were strings. Any insight or help would be greatly appreciated. Thank you in advance This first snippet of code is what I've tried and it gives me a Object is an invalid React child error.

class Board extends React.Component {
  renderSquare(i) {
    return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i) } />;
  }

  render() {
    let board = null;
    for(var i = 0; i < 9; i+=3)
    {
        let row = <div className="board-row">{this.renderSquare(i)}{this.renderSquare(i+1)}{this.renderSquare(i+2)}}</div>
        board = <div>{{board}}{{row}}</div>; 
    }

    return (
        <div>
            {board}
        </div>
    );
  }
}

function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}

class Board extends React.Component {
  renderSquare(i) {
    return (
      <Square
        value={this.props.squares[i]}
        onClick={() => this.props.onClick(i)}
      />
    );
  }

  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>
    );
  }
}
like image 410
Tony Ko Avatar asked Dec 20 '25 21:12

Tony Ko


1 Answers

JSX transforms to React.createElement(...) function calls. These return objects, not strings, so you cannot concatenate them.

Just create an array of elements:

  render() {
    const rows = [];
    for(var i = 0; i < 9; i+=3)
    {
        rows.push(
          <div key={i} className="board-row">
            {this.renderSquare(i)}
            {this.renderSquare(i+1)}
            {this.renderSquare(i+2)}}
          </div>
        );
    }

    return (
        <div>
            {rows}
        </div>
    );
  }

More about lists in React.


it gives me a Object is an invalid React child error.

In

 board = <div>{{board}}{{row}}</div>; 

{board} is an object literal shorthand for {board: board}. Same for {row}. So this really is

board = <div>{{board: board}}{{row: row}}</div>; 

As React tells you, it doesn't know how to render arbitrary objects.

Maybe you wanted

board = <div>{board}{row}</div>;

instead (board and row are React elements after all, so this works), but this would not produce the element structure you want.

like image 61
Felix Kling Avatar answered Dec 23 '25 11:12

Felix Kling



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!