反应useState导致双重渲染

时间:2020-04-06 05:25:16

标签: reactjs react-hooks

考虑典型的useState示例:

import React, { useState } from 'react';

const MyComponent = () => {
  const [count, setCount] = useState(0);
  console.log(count);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
      count: {count}
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

export default MyComponent;

单击按钮可使每个状态打印两次。为什么呢?

screenshort

3 个答案:

答案 0 :(得分:10)

console.log放在没有依赖项的useEffect挂钩中,您会发现它实际上实际上渲染两次。

import React, { useEffect, useState } from 'react';

const MyComponent = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(count);
  });
  
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
      count: {count}
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

export default MyComponent;

Edit wonderful-tesla-cf8uu

这是一个很好的组件生命周期图,它列出了基于类的生命周期函数,但是呈现/提交阶段是相同的。

enter image description here

要注意的导入事项是可以在不实际提交的情况下“渲染”组件(即,您在屏幕上看到的常规渲染)。仅console.log就是其中的一部分。效果在“提交”阶段之后运行。

useEffect

...传递给useEffect的函数将运行 将渲染提交到屏幕后。 ...

默认情况下,效果会在每个完成的渲染之后运行,...

反应严格模式

Detecting Unexpected Side-effects

严格模式无法自动为您检测副作用,但是 可以使它们更具确定性,从而帮助您发现它们。 这是通过有意重复调用以下功能来完成的:

  • 类组件constructorrendershouldComponentUpdate方法
  • 类组件静态getDerivedStateFromProps方法
  • 功能组件主体
  • 状态更新程序功能(setState的第一个参数)
  • 传递给useStateuseMemouseReducer的功能

这仅适用于开发模式。

答案 1 :(得分:2)

有关双重重发的更多信息(根据封闭的反应问题)。

这是StrictMode的故意功能。这仅在开发过程中发生,并有助于发现进入渲染阶段的意外副作用。我们只对具有Hooks的组件执行此操作,因为这些组件很可能在错误的地方意外地产生了副作用。

https://github.com/facebook/react/issues/15074

另一个相关的问题在这里。

useState() do double render

答案 2 :(得分:0)

const countRef = useRef(1);
countRef.current += 1;

这种方式渲染会一次执行2次


const countRef = useRef(1);
useEffect(() => {
   countRef.current += 1;
})

这种渲染方式一次执行1次