You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redux更新时如何阻止组件重渲染?

如何阻止Redux中token更新时触发webview组件刷新?

看来你遇到的问题是:定时更新Redux中的token后,组件因为依赖refreshToken而重新渲染,导致<webview>的src被重新赋值,进而触发页面刷新。要解决这个问题,我们可以从切断组件渲染与token更新的关联,或者避免通过修改src来更新token这两个方向入手,以下是几种实用的解决方案:

方案一:手动更新webview的src(不触发组件重新渲染)

我们可以用useRef获取webview的实例,在组件初始化时设置一次src,之后仅在token更新时手动修改webview的src,而不是让组件整体重新渲染。这样既保证了webview能使用新token,又避免了不必要的组件刷新:

import { useRef, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

const SampleComponent = () => {
  const webviewRef = useRef(null);
  const { refreshToken } = useSelector(state => state.auth);
  const dispatch = useDispatch();

  // 初始化:设置初始src并启动定时任务
  useEffect(() => {
    if (webviewRef.current) {
      webviewRef.current.src = `${HOSTNAME}/page/?refresh_token=${refreshToken}`;
    }
    // 启动每小时更新token的定时任务
    window.tokensCron = new CronJob('0 0 * * *', () => {
      dispatch(getTokens());
    });
    // 组件卸载时清理定时任务
    return () => {
      window.tokensCron?.stop();
    };
  }, []); // 空依赖数组,仅执行一次

  // 当token更新时,手动修改webview的src
  useEffect(() => {
    if (webviewRef.current) {
      webviewRef.current.src = `${HOSTNAME}/page/?refresh_token=${refreshToken}`;
    }
  }, [refreshToken]); // 仅在refreshToken变化时执行

  return <webview ref={webviewRef} />;
};

export default SampleComponent;

方案二:完全阻止组件重新渲染(仅使用初始token)

如果你不需要webview在token更新后立即使用新token,只是想阻止组件刷新,那么可以用useMemo固定src的初始值,再配合React.memo阻止不必要的渲染:

import { useMemo, useEffect } from 'react';
import { useSelector } from 'react-redux';

const SampleComponent = () => {
  const { refreshToken } = useSelector(state => state.auth);
  
  // 仅在组件初始化时计算一次src
  const src = useMemo(() => {
    return `${HOSTNAME}/page/?refresh_token=${refreshToken}`;
  }, []);

  // 启动定时任务(保持不变)
  useEffect(() => {
    window.tokensCron = new CronJob('0 0 * * *', () => {
      store.dispatch(getTokens());
    });
    return () => {
      window.tokensCron?.stop();
    };
  }, []);

  return <webview src={src} />;
};

// 使用React.memo阻止组件因无关状态变化而渲染
export default React.memo(SampleComponent);

注意:这种方式下,webview会一直使用初始的token,不会自动更新。如果需要webview使用新token,这个方案并不适用。

方案三:通过postMessage传递新token(最优解,无页面刷新)

如果你的目标是既让webview内部页面获取新token,又完全避免页面刷新,那最好的方式是用postMessage将新token传递给webview内部的页面,而不是修改src:

组件代码:

import { useRef, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

const SampleComponent = () => {
  const webviewRef = useRef(null);
  const { refreshToken } = useSelector(state => state.auth);
  const dispatch = useDispatch();

  // 初始化设置src并启动定时任务
  useEffect(() => {
    if (webviewRef.current) {
      webviewRef.current.src = `${HOSTNAME}/page/?refresh_token=${refreshToken}`;
    }
    window.tokensCron = new CronJob('0 0 * * *', () => {
      dispatch(getTokens());
    });
    return () => {
      window.tokensCron?.stop();
    };
  }, []);

  // token更新时,发送消息给webview内部页面
  useEffect(() => {
    if (webviewRef.current) {
      webviewRef.current.postMessage({
        type: 'REFRESH_TOKEN',
        token: refreshToken
      });
    }
  }, [refreshToken]);

  return <webview ref={webviewRef} />;
};

export default SampleComponent;

webview内部页面代码:

// 在webview加载的页面中添加监听
window.addEventListener('message', (event) => {
  if (event.data?.type === 'REFRESH_TOKEN') {
    // 将新token存储到本地(比如localStorage)或全局状态
    localStorage.setItem('refresh_token', event.data.token);
    // 后续发起请求时使用这个新token即可
  }
});

这种方式完全避免了webview的刷新,同时让内部页面能实时获取最新的token,是最推荐的方案。

内容的提问来源于stack exchange,提问作者Valerxx22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 11:12:32