Search code examples
javascriptarraysreactjsmultidimensional-arraybacktracking

How do I cycle through the elements of an array inside of a div tag one by one in React


So, I have a huge array of 2d arrays. Each 2d array is basically a step of my backtracking algorithm finding a sudoku solution. I want to find a way display each step in a table. I already have the css and all that. I just need a way to cycle through all of the steps, one after the other, in the same table. Kind of like those animations the explain how backtracking takes place.

Is there a way I can do this? I don't think you need any code, but I'll paste a pic of the array of 2d arrays [I guess you can call it a 3d array] in the console.

The 3d array in google chrome console

PS: Also, directly using document.getElementById('output').innerHTML is not working, both in the function that solves the sudoku itself, and in another for loop in useEffect Hook.

This is what I have so far.


function sleep(milliseconds) {
        const date = Date.now();
        let currentDate = null;
        do {
          currentDate = Date.now();
        } while (currentDate - date < milliseconds);
}

useEffect(()=>{
        results = solve(matrixx,n); //returns 3D array of format [[sudoku board],[sudoku board],[sudoku board]...], each sudoku board is a 2d array in which each element array is one row.
        console.log(results.length)
        var result = results.filter((i,idx) => results[idx-1] !== i) //Removes any duplicate sudoku boards right next to each other
        console.log(result)
        for(var k in result){
            document.getElementById('output').innerHTML = JSON.stringify(result[k]) //Tag with output is a div tag temporarily. I expected this code to fill the div tag with one sudoku board, wait for 10 milliseconds and then fill it with the next sudoku board in result. However, what really happens is wait for a long time and then fill the tag directly with the last sudoku board, which is also the solution to the sudoku problem. 
            sleep(10)
        }
    }, [])

Solution

  • This answer was actually given to me by User @T.J. Crowder. He answered this question that was simplified as a normal array, here.

    Assuming this is a functional component, you need to let the component render each state before setting the next. Otherwise, all the state updates get batched together and the component only renders again when they're all done.

    For instance:

        function Example() {
            const [arr, setArr] = useState([1,2,3,4,5,6,7,8,9,0]);
            // Set up a timer on mount, remove it on dismount and when
            // we run out of values to show
            useEffect(() => {
                const handle = setInterval(() => {
                    // Note useing the callback function, so `arr` isn't stale
                    // in this callback
                    setArr(a => {
                        if (a.length) {
                            // Update the array, dropping the first entry
                            return a.slice(1);
                        }
                        // No more entries, stop the timer
                        clearInterval(handle);
                        return a;
                    });
                }, 500);
                return () => clearInterval(handle);
            }, []);
            return <div>{arr.join()}</div>;
        }