react / react/yoga

Incorrect layout for custom MeasureFunction nodes caused by stale available width information

Open
#1,784 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
18.9k
Forks
1.6k
Avg merge
1m
Merged PRs (30d)
1

Description

Sometimes in our app when the panel is resize slowly from width 140 to width 180 the text with wrapping enabled gets MeasureFunction invoked with incorrect width (e.g. for panel width 140 it is called with 120 (correct), 160 is called with 140 (correct), 161 is called with 121 (incorrect). There are other elements inbetween, and it is inside a 35 percent width container, so I could imagine it is a difficult scenario to support for the algorithm.

It is fixed by setting bool needToVisitNode to true unconditionally (but obviously that destroys performance).
It is also fixed by marking dirty all the descendant wrapping text elements of the resized panel (but it is annoying as it means iterating whole tree below them to find all the wrapping texts).

Finally we were able to fix it with what feels a bit more proper of a solution: we propagate bool sizeChange through the function calls starting at calculateLayoutInternal, it starts with false, but if we meet any node along the recursion that has its style's dimensions changed, we set it to true, and from there on always visit nodes in that recursion chain. We update the layout's LastWidth and LastHeight in the same place LastOwnerDirection is currently getting updated.
We have not noticed noticeable performance degradation, however we do not have many resizing scenarios (no animations yet). So we remain sceptical to that fix, and would love if someone from the team would take a look and evaluate it.

We are sorry for no minimal repro, we tried using the Yoga playground, however it does not allow usage of percentage dimensions, which we believe is crucial for the repro which involves a container X with percentage width dimension, and inside it are fixed width spacer followed by wrapping text, and the parent of X gets resized (and gets marked dirty), however it is not sufficient to cause Yoga without this new fix to update the wrapping text correctly every time (as mentioned, rare times the measure function is called with outdated available width, also known as inner width). We tried disabling caching for custom measure function node, always vising wrapping texts and other cheaper fixes, but none of them are sufficient.

Image

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing calculateLayoutInternal and the needToVisitNode decision during percentage-width parent resizing, using the described custom MeasureFunction scenario as the target behavior. Compare how LastWidth and LastHeight are updated with LastOwnerDirection, and evaluate whether propagating sizeChange avoids stale available widths without always visiting descendants. Done means wrapping text receives current inner widths without the proposed performance cost.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
frontend, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.