React Hooks:延迟加载中断useLayoutEffect吗?

时间:2019-02-16 07:07:58

标签: reactjs react-hooks

我的Web应用程序具有一个可以更改高度的顶部导航栏。它固定在屏幕顶部,css位置:固定。为了将页面内容移到它下面,我有一个间隔div,它会更新其高度以匹配标题的高度,然后将其他所有内容向下推。

我正在更新我的应用程序以使用React挂钩。我有一个useLayoutEffect钩子,该钩子检查导航栏的高度并更新间隔物的高度以匹配。根据{{​​3}}:

  

与componentDidMount或componentDidUpdate不同,使用useEffect安排的效果不会阻止浏览器更新屏幕。这使您的应用程序感觉更灵敏。大多数效果不需要同步发生。在不常见的情况下(例如,测量布局),存在一个单独的useLayoutEffect挂钩,其API与useEffect相同。

我似乎发现,React延迟加载中断useLayoutEffect。这是一个CodeSandBox:

React docs

导航栏隐藏了一个div,其中包含文本“如果可以看到此USELAYOUTEFFECT正在工作”。使用直接导入时,该文本上方的div的大小将与导航栏匹配,将文本向下推到导航栏下方,该文本将变为可见。使用React.lazy时,useLayoutEffect(在AppBarHeader.js中)无法正常工作。

延迟加载发生在App.js中:

//LOADING <COUNTER/> THIS WAY WORKS
// import Counter from "./Counter";

//LAZY LOADING <COUNTER/> THIS WAY BREAKS useLayoutEffect
const CounterPromise = import("./Counter");
const Counter = React.lazy(() => CounterPromise);

我想念什么?

1 个答案:

答案 0 :(得分:1)

对于在useLayoutEffect内某个组件被延迟加载的组件,在执行Suspense时似乎确实是一个错误。如果AppBarHeader是延迟加载的,而Counter不是,则可以正常工作,但是在Counter延迟加载的情况下,AppBarHeader的{​​{1}}会在完全呈现之前执行在DOM中(高度仍为零)。

This sandbox以一种非常骇人听闻的方式“修复”,有助于进一步证明正在发生的事情。

我在useLayoutEffect中添加了以下内容:

App.js

,然后将其传递给 replaceRefHeader = () => { this.setState({ ref_header: React.createRef() }); };

Counter

然后在<Counter replaceRefHeader={this.replaceRefHeader} history={routeProps.history} /> 中输入

Counter

然后将const Counter = ({ replaceRefHeader }) => { useLayoutEffect(() => { replaceRefHeader(); }, []); 放入[props.ref_header]的{​​{1}}的依赖项数组中。

我不建议您这样做(尽管类似的方法可以作为临时解决方法)。这只是为了更清楚地说明计时问题。

我在这里记录了一个新问题:https://github.com/facebook/react/issues/14869