-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes issues with Text backgroundColor #8408
Conversation
There were two issues with the Text backgroundColor prop: 1. Changes to the backgroundColor prop on virtual text nodes did not update their corresponding TextHighlighters 2. Changes to the underlying text did not update the TextHighlighter ranges This change forces a refresh of all TextHighlighters any time: 1. A raw text node changes text value 2. A virtual text node is added or removed from the text tree 3. A virtual text or root text node updates its backgroundColor prop Fixes microsoft#7569 Fixes microsoft#8407
This is not very efficient. It means we do a DFS on the text tree every time the text changes to recalculate the TextHightlighters. One optimization we could consider is to maintain state in the text shadow nodes to signal whether the DFS is required. We could do this in one of two ways:
My preference would be the latter. I initially thought that having counts at each node would allow us to prune which parts of the tree we walk, but we always need to do a complete DFS to get correct TextRange values for the highlighter. To go along with the latter approach, the idea would be that any time a RCTText or RCTVirtualText node has a backgroundColor, the RCTText node boolean flag would get set to true. When an RCTVirtualText node removes it's background color, we need to do a DFS to update the TextHighlighters anyway, so at that point we could conditionally reset the flag to false if no highlighters are created. Taking this a step further, if only the root has a backgroundColor set, we can actually avoid the DFS using the Text property on TextBlock. |
Another thing to consider is to keep the highlighters and just update the ranges, but its less memory efficient to maintain a map from virtual text nodes to their corresponding TextHighlighters than to just recompute the set of required highlighters. Also, recalculating the highlighters from scratch feels a bit less bug prone (there are more edge cases to account for). I'm open to reconsidering this option if someone feels strongly about it. |
Maybe related to the issue @chiaramooney has been looking at (#8395)? |
@chrisglein Quite possibly. I believe fast refresh does not re-render the entire tree, just updates props that have changed. If that's the case, I believe fast refresh would suffer the same limitations that programmatically updating a prop through a state change faces. |
Here is a side beside comparison of the before (left) and after (right) for the RNTester TextExample: 2021-08-11.14-34-58.mp4Note that nothing has changed in the UX, though I believe the snapshots will have changed slightly since this simplifies the way highlights are applied and applies highlights to the entire span of text (rather than just the parts that don't have descendant values for highlights). |
Here's a before and after with this change: React.Native.Playground.Win32.2021-08-11.22-06-36.mp4After: React.Native.Playground.Win32.2021-08-11.22-26-12.mp4 |
2d61372
to
65f8730
Compare
4b35582
to
7b00898
Compare
…en setting foreground
@rozele is this ready for merge? |
@NickGerleman yes. |
There were two issues with the Text backgroundColor prop:
This change forces a refresh of all TextHighlighters any time:
TODOs:
Fixes #7568
Fixes #7569
Fixes #8407
Microsoft Reviewers: Open in CodeFlow