首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >找不到名称,尽管它不是引用的类型记录

找不到名称,尽管它不是引用的类型记录
EN

Stack Overflow用户
提问于 2022-08-18 19:37:30
回答 1查看 29关注 0票数 0

我试图访问if语句中的一个值,如下所示:

代码语言:javascript
复制
const Navbar = () => {
  const token = getFromStorage("token");

  

  if (token) {
    const { data, error } = useQuery(
      ["username", token],
      () => getCurrentUser(token),
      { enabled: token.length > 0 }
    );
  }


  return (
    <div className="flex items-center w-full custom-container  self-center py-3 px-4 ">
  <Link href="/">
    <a className="text-2xl text-pgreen font-bold"> conduit</a>
  </Link>

  <div className="flex ml-auto ">
    <ul className="">
      <Link href="" className=" ">
        <a className="text-gray-400 text-base hover:text-gray-600   w-fit h-fit pr-3 ">
          Home
        </a>
      </Link>

      
      {token && data ? (
        <Link href="" className="">
          <a className="text-gray-400 text-base hover:text-gray-600  w-fit h-fit pr-3">
            {data?.user?.username}
          </a>
        </Link>
      ) : null}
    </ul>
  </div>
</div>
  );
};

我正在尝试使用从useQuery钩子中获得的数据,但是在我的jsx中没有从底部读取数据,我得到了无法找到的名称错误

EN

回答 1

Stack Overflow用户

发布于 2022-08-18 21:16:36

constlet是块作用域变量定义语句,因此使用以下代码:

代码语言:javascript
复制
if(somecondition){ // the if starts a block scope here
    const b = 2;
    console.log(b); // won't throw
} // and ends its block scope here
console.log(b); // will throw, b is outside the scope

这就是在你的例子中发生的。

显而易见的解决方案是像这样定义dataerror

代码语言:javascript
复制
let data, error;

if (token) {
  const query = useQuery(["username", token], () => getCurrentUser(token), {
      enabled: token.length > 0,
  });
  data = query.data;
  error = query.error;
}

但我可以自由地告诉你代码中的一些问题。

根据钩子的规则,钩子甚至是自定义的钩子都应该在顶层使用,因此下面的代码违反了这个规则:

代码语言:javascript
复制
if(somecondition){
  useSomeHook() // be it built-in hook like useState or custom hook
}

React的docs 这里中解释了这个规则。引用:

不要在循环、条件或嵌套函数中调用钩子。相反,在任何早期返回之前,始终在React函数的顶层使用Hooks。通过遵循此规则,您可以确保每次组件呈现时都以相同的顺序调用钩子。这就是允许React正确地保留多个useState和useEffect调用之间的钩子状态的原因。(如果你有兴趣的话,我们会在下面对此进行深入的解释。)

将您的代码重构为最佳实践,我们有以下内容:

代码语言:javascript
复制
const token = getFromStorage("token");
const { data, error } = useQuery(
  ["username", token],
  () => getCurrentUser(token),
  {
    enabled: token && token.length > 0, // this way if token doesn't exists enabled will be false and query won't execute
  }
);

在您的示例中,应用此规则可能不会产生任何影响,但React引用以下话解释了该这里背后的原因:

如前所述,我们可以在一个组件中使用多个状态或效果挂钩:

代码语言:javascript
复制
function Form() {
  // 1. Use the name state variable
  const [name, setName] = useState('Mary');

  // 2. Use an effect for persisting the form
  useEffect(function persistForm() {
    localStorage.setItem('formData', name);
  });

  // 3. Use the surname state variable
  const [surname, setSurname] = useState('Poppins');

  // 4. Use an effect for updating the title
  useEffect(function updateTitle() {
    document.title = name + ' ' + surname;
  });

  // ...
} 

那么,如何反应知道哪种状态对应于哪个useState调用?答案是,反应取决于调用钩子的顺序。我们的示例之所以有效,是因为在每个呈现中,Hook调用的顺序是相同的:

代码语言:javascript
复制
// ------------
// First render
// ------------
useState('Mary')           // 1. Initialize the name state variable with 'Mary'
useEffect(persistForm)     // 2. Add an effect for persisting the form
useState('Poppins')        // 3. Initialize the surname state variable with 'Poppins'
useEffect(updateTitle)     // 4. Add an effect for updating the title

// -------------
// Second render
// -------------
useState('Mary')           // 1. Read the name state variable (argument is ignored)
useEffect(persistForm)     // 2. Replace the effect for persisting the form
useState('Poppins')        // 3. Read the surname state variable (argument is ignored)
useEffect(updateTitle)     // 4. Replace the effect for updating the title

// ...

只要Hook调用的顺序在呈现之间是相同的,React就可以将一些本地状态与每个本地状态关联起来。但是,如果我们将Hook调用(例如,persistForm效应)放在条件中会发生什么呢?

代码语言:javascript
复制
//  We're breaking the first rule by using a Hook in a condition
if (name !== '') {
  useEffect(function persistForm() {
    localStorage.setItem('formData', name);
  });
}

在第一个呈现时,名称!== '‘条件是真的,所以我们运行这个钩子。但是,在下一次呈现时,用户可能会清除表单,使条件变为假。既然我们在呈现过程中跳过了这个钩子,Hook调用的顺序就变得不同了:

代码语言:javascript
复制
useState('Mary')           // 1. Read the name state variable (argument is ignored)
// useEffect(persistForm)  //  This Hook was skipped!
useState('Poppins')        //  2 (but was 3). Fail to read the surname state variable
useEffect(updateTitle)     //  3 (but was 4). Fail to replace the effect

React不知道第二个useState Hook调用返回什么。在这个组件中的第二个Hook调用与persistForm效果相对应,就像在之前的呈现过程中一样,但它不再是这样了。从那时起,我们跳过的那个之后的下一个Hook调用也会转移一个,从而导致错误。 这就是为什么必须在组件的顶层调用钩子。如果我们想有条件地运行一个效果,我们可以把这个条件放在我们的钩子里:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73408579

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档