简体   繁体   English

React:useEffect是否保证在组件呈现之前运行?

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

I am trying to update some components in Gatsby.js , based on what url path I am on. 我正在尝试根据我所处的url路径更新Gatsby.js一些组件。

I am using useEffect() to make sure the components only update when location.pathname (the part of the url after the domain) changes. 我正在使用useEffect()来确保组件仅在location.pathname (域后的url部分)更改时才更新。

Here is the code: https://codesandbox.io/s/gatsbystarterdefault-290qv 这是代码: https //codesandbox.io/s/gatsbystarterdefault-290qv

For some reason, useEffect is not using the updated values of the location prop (which is passed to the header component, which in turn wraps every page). 由于某种原因, useEffect没有使用location prop的更新值(它传递给header组件,而header组件又包裹每个页面)。

To reproduce, go to the CodeSandbox above and: 要重现,请转到上面的CodeSandbox并:

  1. Click to page 2, then back again to page 1 单击第2页,然后再返回第1页
  2. See console statements that isHome when re-rendering Header is true while, isHome at NavItemLink is false isHome when re-rendering Headertrue时,请参阅isHome when re-rendering Header控制台语句,而isHome at NavItemLinkfalse

Any idea why useEffect does not get the latest value of location ? 知道为什么useEffect没有得到最新的location值?

As stated in the React documentation on useEffect , useEffect is "similar to componentDidMount and componentDidUpdate ". 关于useEffectReact文档中所述useEffect “类似于componentDidMountcomponentDidUpdate ”。 Meaning yes, it runs only after the component renders. 意思是,它仅在组件呈现后运行。

You need to rerender the header component after changing navLinks . 更改navLinks后,您需要重新呈现标题组件。 I recommend you do this by making navLinks part of the component state with the useState hook: 我建议你以这样做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])

I've created a fork of your code sandbox with the header component updated to use the useState hook like shown above: https://codesandbox.io/s/gatsbystarterdefault-ftogs 我创建了一个代码沙箱的分支,更新了标头组件以使用useState所示的useState钩子: httpsuseState

I would recommand using useMemo instead of useEffect or storing it inside state. 我建议使用useMemo而不是useEffect或将其存储在状态中。 useMemo will compute NavLinks only when it's dependency will change. useMemo只有在依赖关系发生变化时才会计算NavLink。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM