I have this Stopwatch component which has a wired behavior: the stopwatch works perfectly except it stops re-rendering in UI when I comment the line setTest(val => val + 1)
from inside useEffect(). I validated that timeArray
still gets updated with console.log but the <Text>
in UI doesn't. Please help if you notice something not logically correct with the code below:
const Stopwatch = () => {
const [timeArray, setTime] = useState([0,0,0])
const [test, setTest] = useState(0)
useEffect(() => {
const interval = setInterval(() => {
setTime(val => time(val))
setTest(val => val + 1) <-- commenting this line breaks UI re-rendering below of var timeArray!!
}, 1000)
return () => clearInterval(interval)
},[])
return(
<View>
<Text>{timeArray[2]}:{timeArray[1]}:{timeArray[0]}</Text>
</View>
)
}
const time = (value) =>{
value[0]++
if (value[0] == 59){
value[1]++
value[0] = 0
}
if (value[1] == 59 && value[0] == 59){
value[2]++
value[0] = 0
value[1] = 0
}
return value
}
export default Stopwatch
Value returning from time function is setting up the new state for setTime. So to perform state update, you have to spread the values into setTime state.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function App() {
const [timeArray, setTime] = useState([0, 0, 0]);
const [test, setTest] = useState(0);
const time = value => {
value[0]++;
if (value[0] === 59) {
value[1]++;
value[0] = 0;
}
if (value[1] === 59 && value[0] === 59) {
value[2]++;
value[0] = 0;
value[1] = 0;
}
return value;
};
useEffect(() => {
const interval = setInterval(() => {
const data = time(timeArray);
setTime([...data]);
//setTest(val => val + 1)
}, 1000);
return () => clearInterval(interval);
}, [timeArray]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div>
<p>
{timeArray[2]}:{timeArray[1]}:{timeArray[0]}
</p>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>