注册

为什么react中的hooks都要放在顶部?

1. 使用场景:


公司开会的时候有师兄问到为什么hooks定义一般都写在顶部,对于这个问题我以前总结过,这次看了
react新文档后我给出更加详细的解释并给出具体代码来解释为什么要放在顶部。


2.官网解释:


1.官网截图镇楼:


7f20cfedf69d8418d9f4b9eb16e81362.png


2.那我写在条件语句中会怎样


我给出一段代码:其中const [message, setMessage] = useState('');写在了条件语句里面

import { useState } from 'react';

export default function FeedbackForm() {
const [isSent, setIsSent] = useState(false);
if (isSent) {
return <h1>Thank you!</h1>;
} else {
// eslint-disable-next-line
const [message, setMessage] = useState('');
return (
<form onSubmit={e => {
e.preventDefault();
alert(`Sending: "${message}"`);
setIsSent(true);
}}>
<textarea
placeholder="Message"
value={message}
onChange={e => setMessage(e.target.value)}
/>
<br />
<button type="submit">Send</button>
</form>
);
}
}

效果图:这是一个收集用户反馈的小表单。当反馈被提交时


edf44a992c1ba6a30ed1681e7375b813.png

 它应该显示一条感谢信息,当我点击确定时出现一条错误。


901a7058e302b1d06c639f1b8bbb6f04.png


“渲染的 hooks 比预期的少”


3.那我不写在顶部可能会怎样


下方的const [message, setMessage] = useState('');并没有写在顶部

   import { useState } from 'react';

export default function FeedbackForm() {
const [isSent, setIsSent] = useState(false);
if (isSent) {
return <h1>Thank you!</h1>;
}
const [message, setMessage] = useState('');
return (
<form onSubmit={e => {
e.preventDefault();
alert(`Sending: "${message}"`);
setIsSent(true);
}}>
<textarea
placeholder="Message"
value={message}
onChange={e => setMessage(e.target.value)}
/>
<br />
<button type="submit">Send</button>
</form>
);
}
}

效果图:


3763ef9eab51213222d7ecc4fbffa065.png

 点击确认后:
同样出现这个错误:提前return导致后面一个hooks没有渲染。


32d6c1c45c71dd49b92c01234c96bbb6.png


4.原因分析


从源码的角度来说的话,React会在内部创建一个名为“Hooks”(中文为钩子)的数据结构来追踪每个组件的状态。


在函数组件中调用Hook时,React会根据Hook的类型将其添加到当前组件的Hooks链表中。然后,React会将这些Hooks存储在Fiber节点的“memoizedState”字段中,以便在下一次渲染时使用。


如果你在代码中多次调用同一个Hook,React会根据Hooks的顺序将其添加到当前组件的Hooks链表中。这样,React就可以确定哪个状态应该与哪个组件关联,并且能够正确地更新UI。


以下是一个示例代码片段:

import { useState, useEffect } from 'react';

function useCustomHook() {

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

useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return [count, setCount];
}

export default function MyComponent() {

const [count, setCount] = useCustomHook();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

在上面的代码中,useCustomHook是一个自定义Hook,它使用useStateuseEffectHook来管理状态。在MyComponent中,我们调用自定义Hook并使用返回值来渲染UI。


由于useCustomHook只能在函数组件或其他自定义Hooks的最顶层调用,我们不能将它嵌套在条件语句、循环或其他函数内部。如果这样做,React将无法正确追踪状态并更新UI,可能导致不可预测的结果。如果我们条件渲染中使用可能导致没有引入useCustomHook(),从而导致错误。


总结描述就是创建了一个链表,当在条件语句中使用hooks时可能会导致前后两次链表不同,从而导致错误,所以我们必须尽可能避免这种错误从而写在顶部。


作者:北海天空
链接:https://juejin.cn/post/7223586612927971388
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册