Search code examples
javascriptreactjstic-tac-toe

Can't print String from function (in react tictactoe tutorial)


I'm trying to implement the first improvement after completing the tictactoe react tutorial: Display the location for each move in the format (col, row) in the move history list.

But my (col,row)'s, despite being correctly calculated, aren't being printed in the buttons. My buttons get texts like Go to move #1 (undefined). The (col,row) value should be printed instead of that undefined.

Why is it happening?

Here's my code:

 render() {
  const history = this.state.history;
  const current = history[this.state.stepNumber];
  const winner = calculateWinner(current.squares);

  const moves = history.map((step,move) => {
    const desc = move ? 'Go to move # ' + move + ' ('+getRowCol(history, move)+ ')': 'Go to game start';
    return (
      <li key={move}><button onClick={() => this.jumpTo(move)}>{desc}</button></li>
    )
  });

 (...)

 function getRowCol(history, move){
  let array1 = history[move].squares;
  let array2 = history[move-1].squares;
  array1.forEach((item,index) => {
   if(item !== array2[index]){
    return nomearIndice(index);
   } 
  });
 }
 function nomearIndice(indice){
  let retorno = indice < 3 ? '1,' : indice < 6 ? '2,' : '3,';
  if([0,3,6].includes(indice)){
   return retorno + '1';
  } if([1,4,7].includes(indice)){ 
   return retorno + '2';
  } if([2,5,8].includes(indice)){
   return retorno + '3';
  }
 }

So I run history.map in line 6 of the code sample, this method calls getRowCol function and, as far as I can tell by putting a million console.logs in the code, it works fine. I guess JS isn't waiting until my getRowCol function returns and is producing this undesired result. Is it the problem? If so, how can I fix it?

Thanks in advance


Solution

  • It doesn't look like you are returning anything from getRowCol Try

    function getRowCol(history, move) {
      let array1 = history[move].squares;
      let array2 = history[move - 1].squares;
      return array1.map((item, index) => {
        if (item !== array2[index]) {
          return nomearIndice(index);
        }
      });
    }
    

    Here is a demo using map and returning the result. However, I'm not sure what output you are expecting.

    Can you explain what result you want from getRowCol (eg an example) and I can try to help.

    I've updated the demo to reflect the behaviour you are after using

    function getRowCol(history, move) {
      let array1 = history[move].squares;
      let array2 = history[move - 1].squares;
    
      return array1.reduce((accumulator, item, index) => {
        return (item === array2[index]) ? accumulator : nomearIndice(index);
      }, '');
    }