My Use Case
I am just starting with React (Native) with Hooks and Redux and have some issues understanding some parts of the state update concept for my use case. I am currently working on a React Native App that should update data every full minute. So if the user enters the app at say 11h:31m:27s
,
- the initial state should be shown, then
- a
setTimeout
handles the first update with the offset to reach the full minute (in this case33s
to reach11h:32m:00s
) - a
setInterval
handles the minutely update of the data from now on.
My Issue
Currently, with the below code the console.log("Reducer Fires!")
inside the reducers.js
file is fired increasingly more with every new minute (e.g. only once in the first minute, then two times in the second minute and so on). So I feel that I am still doing something wrong with how I handle the state of my data together with the setInterval()
and setTimeout()
logic. Could somebody review my code below and point me to the errors I am doing?
My Code (so far)
some dummy data
:
export const DATA = [
{"id": 1, "myAttr": 0},
{"id": 2, "myAttr": 4},
{"id": 3, "myAttr": 8},
{"id": 4, "myAttr": 12},
]
the App.js
file with the redux store:
import React from 'react';
import { createStore, combineReducers } from "redux";
import { Provider } from "react-redux";
import { View } from 'react-native';
// Components
import MyComponent from "./components/MyComponent";
import dataReducer from "./store/reducers";
//Create Redux store
const rootReducer = combineReducers({
mydata: dataReducer
});
const store = createStore(rootReducer);
export default function App() {
return (
<Provider store={store} >
<View>
<MyComponent />
</View>
</Provider>
);
}
the actions.js
file storing my Redux action:
//Action to update the data
export const UPDATE_DATA = "UPDATE_DATA";
export const updateData = () => {
return { type: UPDATE_DATA }
}
the reducers.js
file to store the reducers:
import { DATA } from "../data/data";
import { UPDATE_DATA } from "./actions";
// Initial state when app launches
const initState = {
data: DATA
}
const dataReducer = (state = initState, action) => {
switch (action.type) {
case UPDATE_DATA:
//Update an attribute in each object of the data array
const updatedData = state.data.map((i) => {
const newMyAttr = i.myAttr + 1;
return { ...i, myAttr: newMyAttr }
}
)
console.log("Reducer Fires!");
return { ...state, data: updatedData }
default:
return state;
}
};
export default dataReducer;
the component
where I am trying to update the state:
import React, { useEffect, useCallback } from "react";
import { useSelector, useDispatch } from "react-redux";
import { Text, View } from 'react-native';
const MyComponent = (props) => {
const myData = useSelector(state => state.mydata.data);
let start = new Date();
const fullMinuteOffset = (60 - start.getSeconds()) * 1000;
const dispatch = useDispatch();
const saveData = useCallback(() => {
dispatch(updateData())
}, [dispatch]);
useEffect(() => {
const timer = setTimeout(() => {
saveData()
const interval = setInterval(() => {
saveData()
}, 60000)
return () => clearInterval(interval);
}, fullMinuteOffset);
return () => clearTimeout(timer);
}, [saveData, fullMinuteOffset]);
return(
<View>
<Text>{myData[0].myAttr}</Text>
</View>
);
};
export default MyComponent;