React:在组件渲染之前,useEffect 不能保证 运行 吗?

React: Is useEffect not guaranteed to run before the component renders?

我正在尝试更新 Gatsby.js 中的一些组件,基于我所在的 url 路径。

我正在使用 useEffect() 来确保组件仅在 location.pathname(url 域之后的部分)更改时更新。

代码如下: https://codesandbox.io/s/gatsbystarterdefault-290qv

出于某种原因,useEffect 没有使用 location 属性的更新值(它被传递给 header 组件,后者依次包装每一页)。

要重现,请转到上面的 CodeSandbox 并:

  1. 点击第 2 页,然后再次返回第 1 页
  2. 请参阅 isHome when re-rendering Headertrue 的控制台语句,而 isHome at NavItemLinkfalse

知道为什么 useEffect 没有得到 location 的最新值吗?

React documentation on useEffect 中所述,useEffect 为 "similar to componentDidMount and componentDidUpdate"。意思是,它仅在组件渲染后运行。

您需要在更改 navLinks 后重新渲染 header 组件。我建议您使用 useState 钩子使 navLinks 成为组件状态的一部分:

const [navLinks, setNavLinks] = useState([])

useEffect(() => {
    setNavLinks(
        nav.map((navItem, index) => (
            <NavItemLink
              key={navItem.name}
              name={navItem.name}
              to={navItem.path}
              isHome={location.pathname === withPrefix("/")}
            />
        ))
    )
}, [location.pathname])

我已经为您的代码沙箱创建了一个分支,其中更新了 header 组件以使用 useState 挂钩,如上所示:https://codesandbox.io/s/gatsbystarterdefault-ftogs

我建议使用 useMemo 而不是 useEffect 或将其存储在状态中。 useMemo 仅在其依赖性发生变化时才会计算 Nav Links。

const generateNavLinks = path => nav.map((navItem, index) => (
  <NavItemLink
    key={navItem.name}
    name={navItem.name}
    to={navItem.path}
    isHome={path === withPrefix("/")}
  />
));

const navLinks = useMemo(() => generateNavLinks(location.pathname), [location.pathname]);