question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ref value is not accurate in nested mount

See original GitHub issue

I was getting strange results from calling getBoundingClientRect() on a ref value after mounting, the element’s height was always 0. However, when logging the value inside a timeout, it seems to return the actual height. Stranger still is this only happens in nested components.

Nested mount image

import { createElement, mount } from 'forgo';

const List = () => {
  let ref = {};

  return {
    mount: () => {
      console.log(ref.value.getBoundingClientRect()); // 0
      setTimeout(() => console.log(ref.value.getBoundingClientRect()), 0); // 927
    },
    render: () => (
      <div style="overflow: auto; flex-grow: 1" ref={ref}>
        <div style="position: relative; min-height: 0">
          <div style="position: absolute">Hello world</div>
        </div>
      </div>
    )
  }
};

const App = () => {
  return {
    render: () => (
      <div style="display: flex; flex-direction: column; min-height: 100vh">
        <List />
      </div>
    )
  };
};

mount(<App />, document.getElementById('mount'));

“Flat” mount image

import { createElement, mount } from 'forgo';

const App = () => {
  let ref = {};

  return {
    mount: () => {
      console.log(ref.value.getBoundingClientRect());
      setTimeout(() => console.log(ref.value.getBoundingClientRect()), 0);
    },
    render: () => (
      <div style="display: flex; flex-direction: column; min-height: 100vh">
        <div style="overflow: auto; flex-grow: 1" ref={ref}>
          <div style="position: relative; min-height: 0">
            <div style="position: absolute">Hello world</div>
          </div>
        </div>
      </div>
    )
  };
};

mount(<App />, document.getElementById('mount'));

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
spiffytechcommented, Jun 1, 2022

I’ve adapted your code into a reproduction in a sandbox. It’s a different issue than #50.

The order of events looks like:

  1. Forgo starts rendering Parent
  2. Forgo sees Parent includes Child
  3. Forgo renders Child
  4. Forgo calls mount() on Child
  5. Forgo sets the style attr on Parent’s elements

Since Child’s elements won’t be sized correctly without Parent actually being a flex container, you see the height 0 until forgo completes its render (i.e., until after the setTimeout completes).

Forgo needs to be adjusted to call syncStateAndProps() prior to rendering child components. But because of the way forgo stores state or DOM elements, we might need to split up the state sync and props sync into separate steps.

I started working on a failing unit test for this. JSDOM doesn’t set meaningful values in the return value for getBoundingClientRect(), but I think we can assert on the timing of the parent’s attr set (which is the root cause anyway).

0reactions
spiffytechcommented, Aug 3, 2022

This has been released in Forgo v3.2.0.

Read more comments on GitHub >

github_iconTop Results From Across the Web

vue.js - Vue - access nested childs using ref - Stack Overflow
A way of performing parent/deep child, or deep ancestor/sibling communication, for simple scenarios, is using an event hub.
Read more >
v7 register forward refs failed with nested components #4913
Describe the bug register forward refs failed while nesting components. Expected behavior ref to be created properly with the spread ...
Read more >
A complete guide to React refs - LogRocket Blog
Learn how to use React refs, and why it's important to use them only when React can't handle a function call through its...
Read more >
React Stripe.js reference | Stripe Documentation
The Stripe.js reference covers complete Elements customization details. ... to use Element components and access the Stripe object in any nested component.
Read more >
Documentation - SolidJS · Reactive Javascript Library
They track a single value (which can be any JavaScript object) that ... This is useful for nested reactive scopes that you do...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found