skip to Main Content

I have this function that is supposed to input a div and class before and after every 3 items in an array.

Here is the code

  const board_thing = squares.map((item, index) => {
    return (
      <>
        {index % 3 === 0 ? "<div className='board-row'>" : ''}
        <Square value={squares[0]} onSquareClick={() => handleClick(0)}/>
        {index % 3 === 2 ? '</div>' : ''}
      </>
    )
  })

and this is the type of output I want to achieve

      <div className='board-row'>
        <Square value={squares[0]} onSquareClick={() => handleClick(0)}/>
        <Square value={squares[1]} onSquareClick={() => handleClick(1)}/>
        <Square value={squares[2]} onSquareClick={() => handleClick(2)}/>
      </div>
      <div className='board-row'>
        <Square value={squares[3]} onSquareClick={() => handleClick(3)}/>
        <Square value={squares[4]} onSquareClick={() => handleClick(4)}/>
        <Square value={squares[5]} onSquareClick={() => handleClick(5)}/>
      </div>
      <div className='board-row'>
        <Square value={squares[6]} onSquareClick={() => handleClick(6)}/>
        <Square value={squares[7]} onSquareClick={() => handleClick(7)}/>
        <Square value={squares[8]} onSquareClick={() => handleClick(8)}/>
      </div>

But this is the output I’m getting.

enter image description here

3

Answers


  1. When working with JSX, you aren’t working in HTML. You can’t optionally start a tag, then later optionally close it. Instead, chunk your array into groups of three, then output the chunks:

    // This is using one of the many answers to the chunking question linked above,
    // use whichever you like best. You may want to memoize the result.
    const chunks = [];
    for (let i = 0; i < array.length; i += 3) {
        // Remember the items original index, since we need it for `handleClick`
        chunks.push(array.slice(i, i + 3).map((item, index) => ({
            item,
            index: i + index
        }));
    }
    const board_thing = chunks.map((chunk) => (
        <div key={/*???*/} className="board-row">
            {chunk.map(({item, index}) => (
                <Square key={/*???*/} value={item} onSquareClick={() => handleClick(index)}/>
            ))}
        </div>
    ));
    

    Note the placeholders I’ve left for keys. You need to provide keys, and generally shouldn’t use indexes for them.

    Login or Signup to reply.
  2. You need to replace the string with JSX expressions inside curly braces for div with class board-row. You also need to use squares[index] instead of squares[0] . Make use of && to render the div.

    here is the solution:

    const board_thing = squares.map((item, index) => {
      return (
        <>
          {index % 3 === 0 && <div className='board-row'>}
          <Square value={squares[index]} onSquareClick={() => handleClick(index)}/>
          {index % 3 === 2 && </div>}
        </>
      );
    });
    
    Login or Signup to reply.
  3. You must send element directly and not string of elements
    Also, you can refactor the code to send the elements 3 by 3 instead of 1 by 1

    const board_thing = squares.reduce((subArray, item) => {
    if (subArray[-1].length < 3) {
        subArray[-1].push(item)
    }
    else {
        subArray.push([item])
    }
    return subArray
    },[[]]).map((subArray, index) => {
        return (
          <div className='board-row'>
            {subArray.map((item, subIndex) => <Square value={item} onSquareClick={() => handleClick(index*3+subIndex)}/>)}
          </div>
        )
      })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search