我试图访问if语句中的一个值,如下所示:
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中没有从底部读取数据,我得到了无法找到的名称错误
发布于 2022-08-18 21:16:36
const和let是块作用域变量定义语句,因此使用以下代码:
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这就是在你的例子中发生的。
显而易见的解决方案是像这样定义data和error:
let data, error;
if (token) {
const query = useQuery(["username", token], () => getCurrentUser(token), {
enabled: token.length > 0,
});
data = query.data;
error = query.error;
}但我可以自由地告诉你代码中的一些问题。
根据钩子的规则,钩子甚至是自定义的钩子都应该在顶层使用,因此下面的代码违反了这个规则:
if(somecondition){
useSomeHook() // be it built-in hook like useState or custom hook
}React的docs 这里中解释了这个规则。引用:
不要在循环、条件或嵌套函数中调用钩子。相反,在任何早期返回之前,始终在React函数的顶层使用Hooks。通过遵循此规则,您可以确保每次组件呈现时都以相同的顺序调用钩子。这就是允许React正确地保留多个useState和useEffect调用之间的钩子状态的原因。(如果你有兴趣的话,我们会在下面对此进行深入的解释。)
将您的代码重构为最佳实践,我们有以下内容:
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引用以下话解释了该这里背后的原因:
如前所述,我们可以在一个组件中使用多个状态或效果挂钩:
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调用的顺序是相同的:
// ------------
// 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效应)放在条件中会发生什么呢?
// We're breaking the first rule by using a Hook in a condition
if (name !== '') {
useEffect(function persistForm() {
localStorage.setItem('formData', name);
});
}在第一个呈现时,名称!== '‘条件是真的,所以我们运行这个钩子。但是,在下一次呈现时,用户可能会清除表单,使条件变为假。既然我们在呈现过程中跳过了这个钩子,Hook调用的顺序就变得不同了:
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 effectReact不知道第二个useState Hook调用返回什么。在这个组件中的第二个Hook调用与persistForm效果相对应,就像在之前的呈现过程中一样,但它不再是这样了。从那时起,我们跳过的那个之后的下一个Hook调用也会转移一个,从而导致错误。 这就是为什么必须在组件的顶层调用钩子。如果我们想有条件地运行一个效果,我们可以把这个条件放在我们的钩子里:
https://stackoverflow.com/questions/73408579
复制相似问题