如何在 useEffect 中重新渲染 React 功能组件?

问题描述 投票:0回答:3

我有一个顶级组件,它使用一个库来确定用户的浏览器是处于亮模式还是暗模式。然后它被用来设置应用程序的主题,其中包括 HTML Canvas 组件(这很重要,因为它们不像普通的 React 组件那样运行)。目前,如果不重新渲染(页面重新加载或开发模式下的热重新加载),画布组件不会显示正确的主题。

如何让

App
组件在不重新加载的情况下重新渲染?例如,在本地开发模式下,当我点击保存时,只有组件重新渲染,这正是我想在应用程序中复制的行为。

根据 SO 上的其他答案,

useReducer
是在功能组件中强制重新渲染的正确方法,但以下内容对我不起作用:

function App(props) {
  // this is not working 
  const [, forceUpdate] = useReducer((x: number) => x + 1, 0);

  useEffect(() => {
    setDarkMode(getColorTheme() === "dark");
    // this is not working 
    forceUpdate();
  }, [getColorTheme()]);
}
  return (
    <div
      className={(darkMode ? "dark-mode-theme" : "")}
    >
      ...
    </div>
  )
}
javascript reactjs react-hooks html5-canvas
3个回答
0
投票

您是否考虑过使用一个空的依赖数组,以便 useEffect 钩子在组件渲染后运行,然后根据光照模式更新状态?


0
投票

功能组件在以下情况下重新渲染:

  1. 任何道具改变参考身份
  2. useState的setState / useReducer的dispatch被调用
  3. useContext 值更改引用标识

注意:如果下一个状态与前一个状态相同(参照),setState 将中止重新渲染。

dispatch 也有这种行为,当 reducer 的结果返回与之前相同的状态时。

但是看看你的代码,我同意调度不应该中止重新渲染。使用 React DevTools,您可以设置选项让组件在重新渲染时闪烁。换主题时App组件会闪吗?


0
投票

首先,确保您已经根据您的主题在全局 CSS 文件中定义了两个变量属性。然后在你最外层的父组件中,你可以设置数据属性来设置当前主题,如下所示。

  return (
    <div data-theme={theme === "darkMode" ? "dark-mode-theme" : "light-mode-theme"}>
      ...
    </div>
  )

你应该有一种机制来切换模式并将主题作为大多数外部父组件中的状态变量。根据这个实现,你的主题应该根据主题的变化而变化。 下面您可以看到如何在 global.css 文件中保留基于主题的颜色变量。

    body[data-theme="light-mode-theme"] {
  --unnamed-collor-303030: #303030;
  --unnamed-color-565656: #565656;
  --unnamed-color-2f69fe: #2f69fe;
....
}
    body[data-theme="dark-mode-theme"] {
  --unnamed-collor-303030: #303030;
  --unnamed-color-565656: #565656;
  --unnamed-color-2f69fe: #2f69fe;
....
}
© www.soinside.com 2019 - 2024. All rights reserved.