Reputation: 668
I have this custom hook useCountDown which is basically a countdown timer and I'm using it on InputInvestment component i use a dispatch to send count to the store and catch this data via the useSelector and my output is something like:
timerCountdown 10
rerender
timerCountdown 9
rerender
timerCountdown 8
rerender
timerCountdown 7
rerender
timerCountdown 6
rerender
.
.
.
.
As you can see I'm having a rerender problem and I would like to get this countdown data without rerendering my InputInvestment component
useCountDown
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { setTimerCountdown } from 'redux/actions/expirationTimer';
import { useDispatch } from 'react-redux';
const useCountDown = (start) => {
const dispatch = useDispatch();
const timerCountdown = useSelector(state => state.expirationTimer.countdown);
const [counter, setCounter] = useState(start);
useEffect(() => {
if (counter === 0) {
return;
}
setTimeout(() => {
setCounter(counter - 1);
}, 1000);
}, [counter]);
dispatch(setTimerCountdown(counter));
return timerCountdown;
};
export default useCountDown;
InputInvestment component
const InputInvestment = ({ history, offering, userState, attemptToInvest }) => {
const expirationTimer = {
EXPIRATION_TIMEOUT: 15,
EXPIRATION_INTERVAL: 1000,
};
useCountdown(expirationTimer.EXPIRATION_TIMEOUT);
const timerCountdown = useSelector(state => state.expirationTimer.countdown);
// eslint-disable-next-line no-console
console.log('rerender')
// eslint-disable-next-line no-console
console.log('timerCountdown', timerCountdown)
if (timerCountdown === 0) {
const title = 'Investment request expired';
const errorMessage = [
<>
Your investment request has expired due to inactivity. If you would like
to invest in {offering.title}, please{' '}
<Link to={`/offering/${offering.urlHash}/`}>click here</Link> to start a
new investment.
</>,
];
return (
<NotificationWrapper>
<NotificationMessage title={title} textList={errorMessage} />
</NotificationWrapper>
);
} else {
...
};
Upvotes: 0
Views: 129
Reputation: 668
My solution to this problem was to put this countdown timer logic directly in the action and dispatch this in InputInvestment component and also I created a boolean instead of retrieving a number in the component, so now the rerendering don't happens anymore :)
Action
export const setTimerRunning = (expirationTime) => dispatch => {
let counter = expirationTime;
const interval = setInterval(() => {
counter--;
// eslint-disable-next-line no-console
console.log('setTimerRunning',counter)
if (counter < 0 ) {
clearInterval(interval);
}
if(counter === 0){
dispatch({
type: SET_TIMER_EXPIRED
});
}
}, 1000);
};
Reducer
import update from 'immutability-helper';
import * as actions from 'redux/actions/expirationTimer';
export const initialState = {
expired: false,
};
const expirationTimer = (state = initialState, action) => {
switch (action.type) {
case actions.SET_TIMER_EXPIRED: {
return update(state, {
expired: {
$set: true,
},
});
}
default:
return state;
}
};
export default expirationTimer;
Upvotes: 1