I have an issue with react-redux / react-toolkit.
I have a state called todos
.
This state is correctly filled with 3 items as you can see here:
This is the code of my todo slice:
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
value: []
};
export const todoSlice = createSlice({
name: 'todos',
initialState,
reducers: {
setTodos: (state, action) => {
state.value = action.payload
},
},
});
export const { setTodos } = todoSlice.actions;
export default todoSlice.reducer;
I’m using Indexed Db to store the todos locally. Therefore I have an interval (with setInterval
in my app.container.js
, which checks if the todos needs to be reloaded.
function App(props) {
const [interval, setInterval] = useState(null);
const dispatch = useDispatch();
const todos = useSelector((state) => state.todos.value);
const { loadTodos, loadTodosFromIndexedDB } = useTodo();
//...
useEffect(() => {
//...
initializeInterval();
//...
},[]);
async function initializeInterval() {
setInterval(window.setInterval(async () => {
await getTodosFromIndexedDB();
},3000)
);
}
async function getTodosFromIndexedDB() {
let todosFromIndexedDb = await loadTodosFromIndexedDB();
if(todos?.length !== todosFromIndexedDb?.length && !Utils.isNullOrUndefined(todosFromIndexedDb)) {
dispatch(setTodos(todosFromIndexedDb));
}
//...
}
return (
//...
)
}
The thing is, that in the function getTodosFromIndexedDB()
, the value of todos
is like the initial todos
value empty array ([]
).
This causes, that the update is being triggered each 3 seconds, but the value of todos in this function stays on empty array ([]
).
The update which is being triggered provides the correct 3 todo items:
What causes that the value of todos
is not correctly in the getTodosFromIndexedDB()
function? Is it an async issue or is it because of a different scope (window.setInterval
)?
Any help or hint is highly appreciated! Many thanks in advance.
2
Answers
I am posting this as an answer to get more room and I have not tested this yet but I feel that initially the todos are an empty array and when you create this function it is stored as empty array in it every time the set interval runs it is using the same todo value. that’s why it is not working but you can use useCallback to recreate this function everytime todos value change
updated code
On first render, you register the
getTodosFromIndexedDB
function as an interval, which as a closure is scoped over the variables of that execution of the component. You could use aref
to get around this: