我使用的是next.js,在客户端有以下代码。
import { useContext, useEffect, useState } from "react";
import Link from "next/link";
import { UserContext } from "../context";
import { useRouter } from "next/router";
const Nav = () => {
const [current, setCurrent] = useState("TEST");
const [state, setState] = useContext(UserContext);
const router = useRouter();
// Check first if we are running client side (vs server side)
// If so, then set state to the pathname. Update on change
useEffect(() => {
console.log("router.asPath ", router.asPath);
console.log("window.location.pathname is ", window.location.pathname);
console.log(typeof window !== "undefined");
if (typeof window !== "undefined") {
console.log("this ran before");
setCurrent(router.asPath);
console.log("this ran after");
console.log("current is ", current);
}
}, [typeof window !== "undefined" && window.location.pathname]);
//...
}
我在控制台得到以下信息...
router.asPath /register
window.location.pathname is /register
true
this ran before
this ran after
current is TEST
我可以看到每个console.log()都在useEffect中触发并返回所有正确的值。但是setCurrent()似乎没有触发。为什么?
3条答案
按热度按时间2wnc66cl1#
当代码**完成运行时,**React将检查是否存在状态更新,并且如果存在,则useState挂钩的值被更新,并且这导致新的呈现,其中新的值是可用的,因此新的数据被显示在UI中。
因此,如果你想看到状态的新值,从你正在记录的地方是不可能的,因为组件还没有重新渲染,然而,由于更新状态会导致一个新的渲染
console.log
,就像JSX中的这样,以便更好地理解发生了什么:weylhg0b2#
setCurrent将是一个异步操作,因此,原始值将在控制台中输出。
如果您想在状态更新完成后执行操作,可以添加另一个useEffect。
例如,添加this将在每次状态值更新时记录:
这里也有非常明确的解释:https://react.dev/reference/react/useState#ive-updated-the-state-but-logging-gives-me-the-old-value
mcvgt66p3#
如果我理解正确的话,您是在问为什么这个“setCurrent(router.asPath);“didn 't fire. it does fire but react does all the set state at the end of the function together.在本例中,在useEffect的末尾。