likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 42

1. 使用场景:

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

2.官网解释:

1.官网截图镇楼:

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

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>
    );
  }
}

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

为什么react中的hooks都要放在顶部? 它应该显示一条感谢信息,当我点击确定时出现一条错误。

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

“渲染的 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>
        );
      }
    }

效果图:

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
评论
请登录