I'm building a react app which solves a sudoku board and visualises the solving algorithm.
I'm trying to convert the class components to functional components, but am not sure how to get the state changes working.
The problematic code is:
async solve() {
await this.sleep(0);
const board = this.state.board;
for (let row = 0; row < 9; row++) {
for (let col = 0; col < 9; col++) {
if (board[row][col] !== 0) {
// can't change filled cells
continue;
}
// try 1 to 9 for the empty cell
for (let num = 1; num <= 9; num++) {
if (App.isValidMove(board, row, col, num)) {
// valid move, try it
board[row][col] = num;
this.setState({ board: board });
if (await this.solve()) {
return true;
} else {
// didn't solve with this move, backtrack
board[row][col] = 0;
this.setState({ board: board });
}
}
}
// nothing worked for empty cell, must have deprived boards solution with a previous move
return false;
}
}
// all cells filled
return true;
}
(Full code here and the app is hosted here)
Here I need async
so I can use sleep()
to visualise the algorithm. I use this.setState({ board: board });
to trigger a re-render everytime the board is mutated.
When trying to convert to a functional component I tried:
useState
hook, I usedconst [board, setBoard] = useState(initialBoard);
and replaced thethis.setState
calls withsetBoard(board)
. This didn't work because the hook is being called in a loop- wrapping
useState
withuseEffect
(i.e.useEffect(() => setBoard(board), [board])
). This didn't compile, gets the errorReact Hook "useEffect" may be executed more than once...
- also looked into
useReducer
but have read it doesn't work well withasync
My questions are:
- Is this even possible to convert to a functional component?
- If yes, what hook should I use and would it require a redesign of my
solve()
function? - Is it even best to convert this from a class component to a functional component?