To give the shortest backstory, I needed a global state and so I moved to redux for the first time.
What I want to do is run a function every 200 or so milliseconds in a component that requires information from redux and will change the state of the component which will usually cause a re-render.
Currently, my function will run but it won't get new information from redux, the value just shows up as the original.
My questions are three: Am I approaching this correctly? Why does my component keep re-rendering? And most importantly, why does redux not give me the correct value?
I tried the following steps to debug but none of them worked:
So here is some code that should give you an idea of the issue (files have been truncated and abstracted to keep the code focused but the issue presents itself anyway when used in this way):
Store.js
import { configureStore } from '@reduxjs/toolkit'
import mySlice from '../features/slice/mySlice'
export default configureStore({
reducer: {
slice: mySlice,
},
})
Next mySlice.js
import { createSlice, current } from '@reduxjs/toolkit'
export const mySlice = createSlice({
name: 'slice',
initialState: {
currentWord: 0,
},
reducers: {
incrementWord: (state) => {
console.log(state.currentWord)
state.currentWord += 1
}
},
})
export const { incrementWord } = mySlice.actions
export default mySlice.reducer
next the component (which is conditionally rendered) MyComponent.js
import React, {useEffect } from 'react';
import { Text} from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import {incrementWord} from '../../features/slice/mySlice';
const MyComponent = () => { // naturally there is more to this function but I think this makes it simpler
const dispatch = useDispatch();
const sentences = () => {return //gets data based on redux}
const currentWord = useSelector((state) => state.game.currentWord);
const tickSentence = ()=>{ // HERE IS WHERE I CANT GET THE DATA
dispatch(incrementWord());
console.log(currentWord) // Always returns 0
}
useEffect(()=>{
setInterval(()=>{tickSentence()}, 1000);
},[])
console.log(currentWord) // returns actual value
// setInterval(()=>{tickSentence()},1000); // If I use this the function works but it keeps making new intervals leading to infinite calls
return (
<Text>{sentences[currentWord]}</Text> // NOT ACTUAL USAGE
)
}
export default MyComponent;
When left running, the log monitor in React Native Debugger shows State : {} 1 key slice: {} many keys currentWord: 581 Thank you guys so much in advance and I am happy to post any information and try any configuration as I have spent many hours on this already.
Edit: copied store code incorrectly.
EDITED
To prevent multiple calls of interval -> clear the interval when component unmount
useEffect(() => {
const yourInterval = setInterval(() => {
console.log('This will run every second');
}, 1000);
return () => clearInterval(yourInterval); // This will clear the interval when component unmounts
}, []);
Wrong slide initialisation here
import { configureStore } from '@reduxjs/toolkit'
import slice from '../features/slice/mySlice'
export default configureStore({
reducer: {
slice: mySlice, // mySlice is undefined, you should pass slice instead
},
})
Solution
To get value of currentWord inside your function you can create a useEffect on currentWord, and call your function inside of it with currentWord as argument.
const yourFunction = (word) => console.log(word)
useEffect(() => {
yourFunction(currentWord)
}, [currentWord]);