【问题标题】: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语句的,我没有贴出完整的代码。
  • 所以贴出完整代码

标签: javascript reactjs redux rerender


【解决方案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;

【讨论】:

    猜你喜欢
    • 2022-01-02
    • 2020-07-20
    • 1970-01-01
    • 2021-11-02
    • 2020-08-22
    • 2022-01-02
    • 2021-11-02
    • 2023-03-03
    • 2021-04-13
    相关资源
    最近更新 更多