【问题标题】:Wrong colors displayed after React renders div to DOMReact 将 div 渲染到 DOM 后显示错误的颜色
【发布时间】:2022-01-04 01:28:04
【问题描述】:

我正在编写一些代码来将随机颜色映射到行中的单元格。


const COLORS = ['blue', 'green', 'orange', 'red', 'purple', 'yellow'];

const createRandomColors = () => {
  const randomColors = [];
  for (let i = 0; i < COLORS.length; i++) {
    const randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
    randomColors.push(randomColor);
  }
  return randomColors;
}

const App = () => {
  const row = useMemo(createRandomColors, []);

  console.log(row);

  const cells = useMemo(() => row.map((cell, cellIndex) =>
    <div key={cellIndex} style={{ backgroundColor: cell }}>{cellIndex}</div>
  ), [row]);

  cells.forEach(cell => console.log(cell.props.style.backgroundColor));

  return (
    <div className="app">
      <div className="row">
        {cells}
      </div>
    </div>
  );
};

export default App;

问题在于,在渲染 div 元素后,它们具有完全不同的内联样式背景颜色,这是在映射 div 时指定的。

请查看CodeSandBox 并查看控制台日志和呈现的真实结果。 为什么会这样?

【问题讨论】:

    标签: html reactjs dom jsx


    【解决方案1】:

    这看起来很奇怪的原因与在您的 index.html 文件中使用 &lt;StrictMode&gt; 有关。如果您删除 &lt;StrictMode&gt;,您将看到您的代码按您预期的方式运行。但是不要那样做,你确实有一个错误。

    React 希望函数式组件是幂等的,这意味着它们没有副作用。为了帮助你捕捉副作用,React 会在渲染时调用你的代码两次。 see strict mode 通过这样做,它有助于发现微妙的问题,例如您目前遇到的问题。

    一种解决方案是使用useEffect() 创建一次随机颜色。另一种是在功能组件之外生成颜色。

    更新 如果它解决了您的问题,请将答案标记为“已接受”。你是对的。 useMemo 将保存计算,因此除非依赖关系发生变化,否则不会重新计算。但是,react 会故意调用您的代码两次(仅在调试模式下),以帮助您在类或钩子中捕获无意的副作用。使用严格模式时,就好像您拥有两个组件而不是一个。即

    /* StrictMode in debug */
    <StrictMode>
      <App/>
    </StrictMode>
    
    /* ... be like this: */
    <>
      <App/>
      <App/>
    </>
    

    如果您(暂时)删除&lt;StrictMode&gt; 标记,您将看到您的代码按预期工作。如果您添加的代码会导致组件再次呈现(例如点击计数器),那么您的 useMemo 应该会阻止每次呈现时重新生成单元格。

    添加控制台日志以在每次调用 createRandomColors() 时打印。由于您的代码被调用了两次,您应该会看到调试日志出现两次,但您没有。为什么不? React surpasses the console.log 第二次调用你的代码。

    在您的代码顶部(第 3 行)添加 const log = console.log,然后将使用 console.log 的所有位置替换为 log,您将全面了解正在发生的事情。

    继续尝试。我们都来过。

    【讨论】:

    • 好的,我已经将colort的行数组放入useState,并在useEffect中调用了颜色创建函数。我仍然在 useMemo 中保留了我的单元格逻辑。现在可以了。但我仍然不明白这是怎么发生的。我认为使用 useMemo 将确保颜色将被保存并且不会重新渲染,除非某些依赖项发生更改。甚至控制台记录单元格数组也会向我显示具有正确 backgroundColor 参数的节点。这是否意味着虚拟 DOM 中有另一组节点我无法控制台日志?我想知道这些是从哪里来的。
    猜你喜欢
    • 1970-01-01
    • 2018-01-02
    • 2012-06-29
    • 2021-10-26
    • 2017-04-20
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多