反应:useEffect是否不能保证在组件渲染之前运行?

时间:2019-05-26 16:14:44

标签: javascript reactjs gatsby

我正在根据所用的URL路径来更新Gatsby.js中的某些组件。

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

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

由于某些原因,useEffect没有使用location道具的更新值(该值传递给header组件,而组件依次包装每个页面)。

要进行复制,请转到上方的 CodeSandbox ,然后:

  1. 单击第2页,然后再次返回第1页
  2. 查看控制台语句,其中isHome when re-rendering Headertrue,而isHome at NavItemLinkfalse

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

2 个答案:

答案 0 :(得分:3)

React documentation on useEffect中所述,useEffect“类似于componentDidMountcomponentDidUpdate”。意思是,它仅在组件渲染后运行。

您需要在更改navLinks之后重新呈现标头组件。我建议您使用navLinks钩子使useState成为组件状态的一部分:

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])

我已经创建了代码沙箱的派生文件,其标头组件已更新为使用useState钩子,如上所示:https://codesandbox.io/s/gatsbystarterdefault-ftogs

答案 1 :(得分:2)

我会建议使用useMemo而不是useEffect或将其存储在状态中。仅当依赖关系更改时,useMemo才会计算NavLinks。

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