使用自定义挂钩时的重新渲染问题
Posted
技术标签:
【中文标题】使用自定义挂钩时的重新渲染问题【英文标题】:Rerendering problem when using a custom hook 【发布时间】:2021-12-06 18:16:32 【问题描述】:我有这个自定义钩子 useCountDown,它基本上是一个倒数计时器,我在 InputInvestment 组件上使用它em> 我使用调度将计数发送到商店并通过 useSelector 捕获此数据,我的输出类似于:
timerCountdown 10
重新渲染
timerCountdown 9
重新渲染
timerCountdown 8
重新渲染
timerCountdown 7
重新渲染
timerCountdown 6
重新渲染
.
.
.
.
如您所见,我遇到了重新渲染问题,我想在不重新渲染我的 InputInvestment 组件
的情况下获取此倒计时数据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 组件
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
...
;
【问题讨论】:
如果你不打算使用状态变量,为什么还要它? @RobertoZvjerković 到底是哪一个?timerCountdown
我是用来做if语句的,我没有贴出完整的代码。
所以贴出完整代码
【参考方案1】:
我对这个问题的解决方案是将这个倒数计时器逻辑直接放在操作中并在 InputInvestment 组件中调度它,并且我创建了一个布尔值而不是在组件中检索一个数字,所以现在不再发生重新渲染: )
动作
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);
;
减速器
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;
【讨论】:
以上是关于使用自定义挂钩时的重新渲染问题的主要内容,如果未能解决你的问题,请参考以下文章
在 WordPress 中更新自定义 PageLine 的部分时的操作挂钩