Reputation: 1364
There is a board game that every time the user changes something in one square in it is affect the status of all other squares. To change a square's state I use useReducer
, and to handle the change on the other squares I use useEffect
.
The problem is when the user requests the computer to resolve by own the situation (there is such an option). My preferred solution is to trigger a recursive function (resolveBoard
) that goes over all the squares and change them, one after one. The calculation on what to do in each square is based on the side effect of the former decision in the previous squares (what should be done by the useEffect
mentioned above).
Unfortunately, the useReducer
's dispatcher (and, as result, the useEffect
) is be called only after the recursive function finished to go all over the board, which spoils the calculation and causes it returns an incorrect result.
How it can be done?
const [squaresValues, dispatchSquaresValue] = useReducer(
setSquaresValue,
{ rows: props.rows, columns: props.columns },
InilizeBoard
);
useEffect(() => {
calculateValues();
}, [squaresValues]);
function resolveBoard(row, index) {
...
if (resolveSingleSquare(row, index)) {
const nextIndex = ...
const nextRow = ....
return resolveBoard(nextRow, nextIndex);
}
return false;
}
function resolveSingleSquare(row, index) {
...calculations based on the state of the others squares
if (working) {
dispatchSquaresValue(squareProp);
return true;
}
return false;
}
function setSquaresValue(prevValues, squareProp) {
--- be called only after all finished:(
}
Upvotes: 1
Views: 532
Reputation: 11156
Ciao, in order to dispatch dispatchSquaresValue
before re-call resolveBoard(nextRow, nextIndex);
you have to use a Promise mechanism. So you cannot use useReducer
. There are several ways to solve your problem, I used 2:
redux-promise:
export const updateSquareValue = (key, value)=>
Promise.resolve({
type:'UPDATE_SQUARE_VALUE',
key, value
})
Then in your component:
import { useDispatch } from 'react-redux';
...
const dispatch = useDispatch();
...
function resolveBoard(row, index) {
...
dispatch(updateSquareValue(squareProp)).then(() => {
resolveBoard(nextRow, nextIndex);
});
}
redux-thunk:
export const updateSquareValue = (key, value) => dispatch => {
dispatch({
type: 'UPDATE_SQUARE_VALUE',
key,
value,
});
return Promise.resolve();
};
Then in your component:
import { useDispatch } from 'react-redux';
...
const dispatch = useDispatch();
...
function resolveBoard(row, index) {
...
dispatch(updateSquareValue(squareProp)).then(() => {
resolveBoard(nextRow, nextIndex);
});
}
Upvotes: 1