为什么会渲染这个组件?

3
尽管我掌握了基础知识,但似乎我仍然在努力奋斗。我有一个例子。
const Component = () => {
  const [state, setState] = useState("");
  useEffect(() => {
    console.log("useEffect");
    setState("Nebil");
  }, [state]);

  console.log("component rerender ", state);
};
export default Component;

通过上述代码,我看到了以下输出。
component rerender
useEffect
component rerender Nebil 
useEffect
component rerender Nebil 

我想知道为什么第二次触发useEffect时,它会更新状态并导致重新渲染。我以为当值等于"Nebil"并且我们将状态设置为"Nebil"时,由于它是一个字符串,这不会重新渲染组件。你能解释一下吗?
注意:我没有使用strictmode。
2个回答

3

嗯,在这里对每个console.log进行解释

组件重新渲染
默认状态是""

useEffect
useEffect由默认state""触发

组件重新渲染Nebil
useEffect中,状态已更改为"Nebil"

useEffect
由于状态已更改,useEffect由状态"Nebil"触发

组件"rerender" Nebil
由于useEffect已被触发,函数(Component本身是一个函数)将被执行,但即使您看到console.log输出,虚拟DOM不会更新,因为它与之前的相同,所以不会触发额外的渲染。您应该尝试添加return语句并使用一个开发工具,该工具会用绿色突出显示更新的DOM部分,我认为React开发工具有相关功能。


3
这并没有解释为什么最后的日志会出现。如果你只有在state !== 'Nebil'的时候才设置state,最后的渲染就不会发生。这表明使用相同值进行setState会导致渲染,我不认为这是useEffect特定的行为。 - Oktay Yuzcan
3
它没有解释为什么最后一个日志会发生。如果你只在状态不等于'Nebil'时设置状态,最后的渲染就不会发生。这就导致了这样的结论:使用相同的值调用setState会引起渲染,我不认为这是useEffect特有的东西。 - Oktay Yuzcan
即使我将console.log放在jsx内部,仍然看到相同的输入,这意味着组件正在重新渲染,很抱歉,我还是没有理解你的观点。 - nebil
即使我将console.log放在jsx内部,仍然看到相同的输入,这意味着组件正在重新渲染,很抱歉,我还没有理解你的观点。 - nebil
我没有这个扩展,但即使你对组件进行无限渲染,也不会有任何更新,只会导致组件无限渲染。 - nebil
显示剩余6条评论

3
useEffect是React Hook的一种,它允许你将组件与外部系统进行同步,或者在你的情况下,将其与状态进行同步。
通过将依赖状态传递给useEffect,React将比较该状态与其先前的值。因此,由于你在useEffect内部设置了状态,这将导致组件重新渲染,因为状态从初始值发生了变化。以下是发生的情况:
1. 初始组件渲染 2. 在初始渲染时执行useEffect 3. 由于setState的原因,再次组件渲染 4. 由于依赖项从""更改为"Nebila",执行useEffect 5. 现在我们不会执行useEffect,因为你设置了相同的状态值,如果在ue中初始化一个新对象,你将进入无限循环!
尝试将初始状态设置为"Nebil" useState("Nebil"),useEffect只会在初始渲染时触发一次。
请确保删除strictMode,因为你的组件将多次重新渲染,以查找由于不纯的渲染而引起的错误。
我创建了一个沙盒来检查渲染计数 https://codesandbox.io/s/long-cookies-s4vjg6?file=/src/App.js 以下是一些有用的参考资料:

请问你能否详细解释一下“5. useEffect中的依赖变化导致组件重新渲染”?我原以为只有在状态更新时组件才会重新渲染,但事实并非如此。 - nebil
请问你能否详细解释一下"5. useEffect中由于依赖项变化而导致组件重新渲染"?我以为只有在状态更新时组件才会重新渲染,但事实并非如此。 - nebil
请问你能否详细解释一下"5. useEffect中由于依赖项变化而导致组件重新渲染"?我原以为组件只有在状态更新时才会重新渲染,但事实并非如此。 - undefined
你说得对,我修改了我的解释并为你创建了一个沙盒供你检查。 - Charles Semaan
你是对的,我修改了我的解释并为你创建了一个沙盒供你检查。 - Charles Semaan
你说得对,我已经编辑了我的解释,并为你创建了一个沙盒供你检查。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接